I need some help with creating a script for the enemies in my game! I'm making a 2.5D game where you chase campers and try to kill them. I'm mostly done with the game, but I can't get the AI to work! I've looked around for scripts and help for a couple of days now but can't find anything that fits well with the rest of my game... Please help!
For my ground i have a flat surface rotated at 35 on the x-axis, which have worked pretty well for me so far (moving the character around and placing obstacles).
At this point I'm working on this script;
#pragma strict
//Attack button
var attackButton : Joystick;
var anim : Animator;
var delay = 5.0;
//Player can kill
var CanKill = false;
//Score
var scoreValue : int;
var killValue : int;
var playerControl : PlayerControl;
//AI
var speed : int = 2;
var Damp: float = 1.0;
var isRun: boolean = false;
var Target: Transform;
var detectionRange: int = 5;
private var character : CharacterController;
function Start ()
{
anim = GetComponent("Animator");
var playerControlObject : GameObject = GameObject.FindWithTag ("Player");
character = GetComponent(CharacterController);
}
function WaitAndDestroy()
{
yield WaitForSeconds(delay);
Destroy (gameObject);
}
function Update()
{
//Can the player kill?
if (attackButton.tapCount == 1)
CanKill = true;
else CanKill = false;
//AI
var FromPlayer = Vector3(Target.position.x - transform.position.x, 0);
if(FromPlayer.magnitude <= detectionRange){
isRun = true;
}
if(FromPlayer.magnitude >= detectionRange) {
isRun = false;
}
if(isRun) {
RunAway();
anim.SetBool("Walk", true);
}
else anim.SetBool("Walk", false);
}
function OnTriggerEnter (Other : Collider){
if(Other.gameObject.tag == "Player" && CanKill == true) {
playerControl.AddScore (scoreValue);
playerControl.AddKills (killValue);
anim.SetTrigger("Dead");
WaitAndDestroy();
}
}
function RunAway()
{
var moveDirection : Vector3 = transform.position;
character.Move(moveDirection.normalized * speed * Time.deltaTime);
}`
Which kinda works, but for some reason the character stops in the middle of the level and just runs in place... I would also like him to turn and run the other direction if I (the player) catches him and runs in front of him. (If the code is a little messy I apologize, but as I said I'm new to Javascript).
i would done those two changes.
At first:
var FromPlayer = transform.position - Player.transform.position;
cause you want subtract whole vectors not just x coordinates
and second:
function RunAway( FromPlayer :vector3 )
{
character.Move(FromPlayer.normalized * speed * Time.deltaTime);
}
if you have already vector FromPlayer you can directly use it for moving character
i personally never used unity but that is how you would done it anywhere else. It of course assume that positions can be substracted as vectors
You want the campers to run away from the player right? Then you should do
Vector3 moveDirection = transform.position - Player.transform.position
To get the direction they should run in. Then do the line you already have
character.Move(moveDirection.normalized * speed * Time.deltaTime);
Related
I'm trying to make a simple game in Unity for GearVR. In the game I have a scene where the user can navigate through a list of items. An item can be selected if the user clicks while looking at one. For the navigation part, the user should be able to use both head movement and swipe to rotate the items (shifting by one/minus one at every right/left swipe).
Now the problem: I can make all of this work with the code below (set as component to the parent of the items), but the rotation keeps increasing the more I use swipes. I can't seem to figure out why ... still working on it.
Any kind of help is appreciated XD
private void ManageSwipe(VRInput.SwipeDirection sw)
{
from = transform.rotation;
if (sw == VRInput.SwipeDirection.LEFT)
{
to = Quaternion.Euler(new Vector3(0, from.eulerAngles.y + 30, 0));
}
if (sw == VRInput.SwipeDirection.RIGHT)
{
to = Quaternion.Euler(new Vector3(0, from.eulerAngles.y - 30, 0));
}
StartCoroutine(Rotate());
}
IEnumerator Rotate(bool v)
{
while (true)
{
transform.rotation = Quaternion.Slerp(from, to, Time.deltaTime);
yield return null;
}
}
I'm using Unity 5.4.1f1 and jdk 1.8.0.
PS. Don't be to hard on me, since this is my first question here.
By the way ... hello everyone XD
You fixed most of the problems I discussed in the comment section. One things left is still the while loop. Right now, there is no way to exit that while loop and this will result to multiple instance of the Rotate function running at the-same time.
but the rotation keeps increasing the more I use swipes
Solution is to store reference to one coroutine function then stop it before starting a new one.
Something like this.
IEnumerator lastCoroutine;
lastCoroutine = Rotate();
...
StopCoroutine(lastCoroutine);
StartCoroutine(lastCoroutine);
Instead of while (true), you should have a timer that exists the while loop. At this time, the Rotate function is continuously running. You should make it stop after moving from the rotation to the destination rotation.
Something like this should work:
while (counter < duration)
{
counter += Time.deltaTime;
transform.rotation = Quaternion.Lerp(from, to, counter / duration);
yield return null;
}
Here is what your whole code should look like:
IEnumerator lastCoroutine;
void Start()
{
lastCoroutine = Rotate();
}
private void ManageSwipe(VRInput.SwipeDirection sw)
{
//from = transform.rotation;
if (sw == VRInput.SwipeDirection.LEFT)
{
to = Quaternion.Euler(new Vector3(0, from.eulerAngles.y + 30, 0));
}
if (sw == VRInput.SwipeDirection.RIGHT)
{
to = Quaternion.Euler(new Vector3(0, from.eulerAngles.y - 30, 0));
}
//Stop old coroutine
StopCoroutine(lastCoroutine);
//Now start new Coroutine
StartCoroutine(lastCoroutine);
}
IEnumerator Rotate()
{
const float duration = 2f; //Seconds it should take to finish rotating
float counter = 0;
while (counter < duration)
{
counter += Time.deltaTime;
transform.rotation = Quaternion.Lerp(from, to, counter / duration);
yield return null;
}
}
You can increase or decrease the duration variable.
Try to use Lerp from the current Rotation not the last one:
transform.rotation = Quaternion.Slerp(transform.rotation, to, Time.deltaTime);
I have been making endless jumping game.
It is lacking powerbar.. I have managed to make one but it does not scale with the screen change.. I tried to use canvas to world screen but bar won't face the direction you click..
So like the longer you hold left mouse click, more power it has and it faces the direction you click.. Atleast it should do that, and i does but only on one screen size.
It looks likes this:
http://prntscr.com/b6z5wn
So this is the code i am currently using..
function Start ()
{
powerFill_startPos = powerFill.transform.localPosition.x;
powerFillAccel = 770 * Time.deltaTime;
}
function Update ()
{
if(Input.GetMouseButton(0) && collision.onPlatform == true && delete.jurinoFlag == true)
{
bar_back.enabled = true;
powerFill_Image.enabled = true;
var moveDirection : Vector3 = gameObject.transform.position - Input.mousePosition;
if (moveDirection != Vector3.zero)
{
var angle : float = Mathf.Atan2(moveDirection.y, moveDirection.x) * Mathf.Rad2Deg;
angle -= 180;
transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
}
powerFill.transform.localPosition.x += powerFillAccel;
}
else
{
bar_back.enabled = false;
powerFill.transform.localPosition.x = powerFill_startPos;
powerFill_Image.enabled = false;
}
}
I would very much appreciate any help i can get so i can finish the game and publish it :)
Thanks for taking time and replying. Have a nice day!
i have a problem here,
i have an object called projectile and i want make that projectile appear where i touch my phone with screen resolution 1090x1820, my logic is :
#pragma strict
var projectile:Transform;
private var shoot:Transform;
function Start () {
}
function Update () {
for (var i = 0; i < Input.touchCount; ++i) {
var touch:Touch = Input.GetTouch(i);
if (touch.phase == TouchPhase.Began) {
shoot = Instantiate(projectile) as Transform;
shoot.position.x = touch.position.x;
shoot.position.y = touch.position.y;
}
}
}
This code work well, except the projectile doesn't appear at screen.
Somehow, i try to put an object at unity editor and it's showing x = -2 and y = -1 or x =-1 and y =-5 and so on.I also try to Debug the touch position and it's showing x= 300 and y=90 etc.
How i can fix this ?
Sorry for my bad english !
Your problem is you are intermixing world coordinates with screen position. To fix that you'll need to use ScreenToWorldPoint so your code would look similar to:
var worldPos : Vector3 = camera.ScreenToWorldPoint (touch.position));
shoot.position.x = worldPos.x;
shoot.position.y = worldPos.y;
This is untested code so use only for reference as it is there for you to understand the logic.
Hey guys so I've been trying to solve this for awhile I have looked on many forums and tried to understand what they were trying to convey with the code using ActionScript 3 but i still get nothing. My main goal is to have a character on stage named "mainPlayer" now i want to set up touch events so that when the user drages his finger up down or side to side i want to the mainPlayer to follow the users path or if the user touches a point on the screen and holds his finger there the mainPlayer will be attracted to the touch and move to the point where the finger is currently at on the screen.
Ive seen lots of stuff with Phase and ID implemented but dont really understand whats going on
so far this is what i have set up:
public class realmEngine extends MovieClip
{
//MultiTouch gestures
Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT;
Multitouch.inputMode = MultitouchInputMode.GESTURE;
public var mainPlayer:mcPlayer;
//PlayerControls
private var speed:Number = 8.0;
public var vx:Number = 0;
public var vy:Number = 0;
private var friction:Number = 0.85;
private var maxSpeed:Number = 15;
public function realmEngine()
{
//Add Player to Stage
mainPlayer = new mcPlayer();
stage.addChild(mainPlayer);
mainPlayer.x = (stage.stageWidth / 2) - 300;
mainPlayer.y = (stage.stageHeight / 2 );
//trace("this works");
//Setup Touch Event listeners
mainPlayer.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
stage.addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove);
stage.addEventListener(TouchEvent.TOUCH_END, onTouchEnd);
//Game Loop Event Listener
stage.addEventListener(Event.ENTER_FRAME, gameLoop);
}
private function gameLoop(e:Event):void
{
mainPlayerControls();
}
private function mainPlayerControls():void
{
}
private function onTouchEnd(e:TouchEvent):void
{
}
private function onTouchMove(e:TouchEvent):void
{
}
private function onTouchBegin(e:TouchEvent):void
{
}
}
I'm not sure what to do inside the onTouch Functions in order for the object that i add to stage by Code to follow the users touch on the screen.
Can anyone lead my in the right direction or give me any advice? I woudld really appreciate it thanks guys
Yes I happen to know how to do this, I just wasn't sure if I had grasped fully what you wanted to achieve.
Note that I won't be taking into account the speed and maxSpeed variables for moving the player. It's beyond this scope and beyond the scope of the top of my head. A little bit of internet searching will get you far on that subject however!
First of all, in order to make the object follow a path drawn by the user, we need a way to store the path. For this, I suggest a Vector with Point as its datatype. It's fast and easy to work with when adding and removing elements without having to worry about its length.
We also need a way to tell wether the player sprite should move or not, in other words wether the user is pressing the finger on the screen or not.
private var _pathPoints : Vector.<Point>;
private var _isMoving : Boolean = false;
Easy-cakes. Now for the fun part!
First, we need to change the scope of the onTouchBegin event, from mainPlayer to the stage. If we don't, the user won't be able to touch an abstract point on the stage and get the player sprite to move there. Simply done with a change to
mainPlayer.addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin);
Then we take care of when the user moves his or her finger. Nothing fancy going on here.
We're just simply storing the coordinates in our vector and storing the current state of wether the user is pressing the screen or not.
private function onTouchBegin ( e:TouchEvent ) : void
{
_pathPoints.push( new Point( e.stageX, e.stageY ) );
_isMoving = true;
}
private function onTouchMove ( e:TouchEvent ) : void
{
_pathPoints.push( new Point( e.stageX, e.stageY ) );
}
private function onTouchEnd ( e:TouchEvent ) : void
{
// Dirty but quick way of clearing the vector
_pathPoints.splice(0);
_isMoving = false;
}
Finally, for the even funnier part; the main game loop! Or "Where the Magic Happens".
private function mainPlayerControls () : void
{
// Update player position and forces
vx *= friction;
vy *= friction;
mainPlayer.x += vx;
mainPlayer.y += vy;
// Check if the player should be moving to a new point
if( _isMoving )
{
// Get a reference to the current target coordinate
var target : Point = _pathPoints[0];
// Check if the player position has reached the current target point
// We use a bounding box with dimensions equal to max speed to ensure
// that the player doesn't move across the point, move back towards it
// and start jojo-ing back and forth
if(mainPlayer.x >= target.x - maxSpeed && mainPlayer.x <= target.x + maxSpeed &&
mainPlayer.y >= target.y - maxSpeed && mainPlayer.y <= target.y)
{
// The player has reached its target
//so we remove the first element of the vector
_pathPoints.shift();
// and update the target reference
target = _pathPoints[0];
}
// Calculate velocities to the first element of the vector
vx = mainPlayer.x - target.x;
vy = mainPlayer.y - target.y;
}
}
I am trying to move and object by touching it and dragging. I am testing it on my Samsung Galaxy SIII. I have used the following code. For some reason it moves faster than my finger. It should always be beneath my finger. What is wrong? (note: I haven't done the "move object only if you touch onto it" part, so right now it moves where ever I touch).
#pragma strict
var speed : float = 1;
function Start () {
}
function Update () {
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
// Get movement of the finger since last frame
var touchDeltaPosition:Vector2 = Input.GetTouch(0).deltaPosition;
// Move object across XY plane
transform.position = Vector2.Lerp(transform.position,
touchDeltaPosition,
Time.deltaTime*speed);
}
}
this is what i use, it may be a better option for you, it is based on the camera, the reason that your Vector2.Lerp is not working correctly i think is because of your time variable in it you could refer to this Lerp and tweak your 't' variable until it is good for you, or you can try this, this is what i use, also i subtract from x and add to y so my finger isnt over the graphic, best of luck :)
#pragma strict
var speed : float = 1;
var distance : float = 5;
function Start () {
}
function Update () {
if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) {
// Get movement of the finger since last frame
var touchDeltaPosition:Vector2 = Input.GetTouch(0).deltaPosition;
var touchmove : Vector3 = Vector3(touchDeltaPosition.x, touchDeltaPosition.y, distance);
// Move object across XY plane
transform.position = Camera.main.ScreenToWorldPoint(touchmove);
}
}