How can I make a smooth transition between two animations? - c#

First animation when starting the game the character is examine or typing and then after 10 seconds I want the character to start walking and just before reaching the destination to change to idle.
The order should be : Typing , Walking , Idle
With this script the character is typing waiting 10 seconds rotating looking the target and then move to the target without the two animations Walking and Idle.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class AgentControl : MonoBehaviour
{
public List<Transform> points;
public bool waitTimeToMove = false;
//notice WaitTime is a float now
public float WaitTime = 10f;
public bool randomWaitTime;
float waitMinTime = 1f;
float waitMaxTime = 10f;
public bool loop = false;
private int destPoint = 0;
private NavMeshAgent agent;
private Transform originalPos;
//two vars for handling timer
private float timer = 0;
private float originSpeed;
void Start()
{
agent = GetComponent<NavMeshAgent>();
// Disabling auto-braking allows for continuous movement
// between points (ie, the agent doesn't slow down as it
// approaches a destination point).
agent.autoBraking = false;
originSpeed = agent.speed;
if (randomWaitTime == true)
{
WaitTime = Random.Range(waitMinTime, waitMaxTime);
}
//transforms dont exist without A GameObject and a GameObject doesn't exist without a transform
//create a new GameObject to hold our position
GameObject originalPositionObject = new GameObject();
originalPositionObject.name = "WP";
originalPositionObject.tag = "Waypoint";
originalPositionObject.transform.parent = GameObject.Find("Waypoints").transform;
//set the new gameobjects position equal to where the transform is right now
originalPositionObject.transform.position = transform.position;
//add this to the points list instead
points.Add(originalPositionObject.transform);
}
void GotoNextPoint()
{
// Returns if no points have been set up
if (points.Count == 0)
return;
// Set the agent to go to the currently selected destination.
agent.destination = points[destPoint].position;
// Choose the next point in the array as the destination,
// cycling to the start if necessary.
destPoint = (destPoint + 1) % points.Count;
}
void Update()
{
// Choose the next destination point when the agent gets
// close to the current one.
if (!agent.pathPending && agent.remainingDistance < 1f)
{
//if wait to move is true
if (waitTimeToMove)
{
//if timer is less than 10
if (timer < WaitTime)
{
//add Time.deltaTime each time we hit this point
timer += Time.deltaTime;
}
//no longer waiting because timer is greater than 10
else
{
waitTimeToMove = false;
}
}
//if we hit here waitToMove is false, so go ahead as usual
else
{
if (loop == false && destPoint == points.Count - 1)
{
agent.speed = 0;
}
if (loop == true || destPoint != points.Count - 1)
{
agent.speed = originSpeed;
// Not working if setting back to loop = true in the inspector
// After it was not loop and agent in last waypoint
// When setting to loop = true it's not continue to check why
// Should continue the loop if loop true !
// Loop = true is not working when game is running only on Start
GotoNextPoint();
}
}
}
}
}
In the editor I have an animator controller for the character with 3 states : The touc/examine , walk , idle
The first animation is working fine but it's not changing to walk after 10 seconds and not changing to walk at all. It keep looping the first animation all the time. and the first animation length is more then 0 seconds.
between the first animation state and the second walk state there is a transition and exit time is disabled with one condition Walk True and a parameter I added of type bool name Walk.
between the second state walk and the last state idle also there is a transition and exit time disabled too with condition Walk True.
Screenshot of the first transition :
The main idea is to change transitions smooth between the 3 states and then stop when the last state played without looping. Each state should play once.
What I did so far :
In both transitions disabled Has Exit Time (enabled false)
Then changed the script added a line to start the Walk animation state :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class AgentControl : MonoBehaviour
{
public List<Transform> points;
public bool waitTimeToMove = false;
//notice WaitTime is a float now
public float WaitTime = 10f;
public bool randomWaitTime;
float waitMinTime = 1f;
float waitMaxTime = 10f;
public bool loop = false;
public Animator anim;
private int destPoint = 0;
private NavMeshAgent agent;
private Transform originalPos;
//two vars for handling timer
private float timer = 0;
private float originSpeed;
void Start()
{
agent = GetComponent<NavMeshAgent>();
// Disabling auto-braking allows for continuous movement
// between points (ie, the agent doesn't slow down as it
// approaches a destination point).
agent.autoBraking = false;
originSpeed = agent.speed;
if (randomWaitTime == true)
{
WaitTime = Random.Range(waitMinTime, waitMaxTime);
}
//transforms dont exist without A GameObject and a GameObject doesn't exist without a transform
//create a new GameObject to hold our position
GameObject originalPositionObject = new GameObject();
originalPositionObject.name = "WP";
originalPositionObject.tag = "Waypoint";
originalPositionObject.transform.parent = GameObject.Find("Waypoints").transform;
//set the new gameobjects position equal to where the transform is right now
originalPositionObject.transform.position = transform.position;
//add this to the points list instead
points.Add(originalPositionObject.transform);
anim = GetComponent<Animator>();
}
void GotoNextPoint()
{
// Returns if no points have been set up
if (points.Count == 0)
return;
// Set the agent to go to the currently selected destination.
agent.destination = points[destPoint].position;
// Choose the next point in the array as the destination,
// cycling to the start if necessary.
destPoint = (destPoint + 1) % points.Count;
}
void Update()
{
// Choose the next destination point when the agent gets
// close to the current one.
if (!agent.pathPending && agent.remainingDistance < 1f)
{
//if wait to move is true
if (waitTimeToMove)
{
//if timer is less than 10
if (timer < WaitTime)
{
//add Time.deltaTime each time we hit this point
timer += Time.deltaTime;
}
//no longer waiting because timer is greater than 10
else
{
waitTimeToMove = false;
anim.SetBool("Walk", true);
}
}
//if we hit here waitToMove is false, so go ahead as usual
else
{
if (loop == false && destPoint == points.Count - 1)
{
agent.speed = 0;
}
if (loop == true || destPoint != points.Count - 1)
{
agent.speed = originSpeed;
// Not working if setting back to loop = true in the inspector
// After it was not loop and agent in last waypoint
// When setting to loop = true it's not continue to check why
// Should continue the loop if loop true !
// Loop = true is not working when game is running only on Start
GotoNextPoint();
}
}
}
}
}
After 10 seconds :
anim.SetBool("Walk", true);
but now I want that a bit before or when the agent get to the target destination to change it to the Idle state animation :
anim.SetBool("Idle", true);
but I'm not sure where to put it in the script. I tried in this place :
if (loop == false && destPoint == points.Count - 1)
{
agent.speed = 0;
anim.SetBool("Idle", true);
}
but it didn't work fine the agent kept walking after the target destination then moved back to the target destination then changed to idle a mess.

Related

I want to make an object fall every 3 seconds, but this does not seem to work. C# Unity

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FallingObject : MonoBehaviour
{
// Variables
float timer = 0;
MeshRenderer renderer;
Rigidbody rigidbody;
// Start is called before the first frame update
void Start()
{
// Cached References
renderer = GetComponent<MeshRenderer>();
rigidbody = GetComponent<Rigidbody>();
rigidbody.useGravity = false;
}
// Update is called once per frame
void Update()
{
// Setup to make a timer work every 5 seconds
timer = timer + Time.deltaTime;
if((timer >= 6) && (rigidbody.useGravity = false))
{
// Makes the item fall after 3 seconds
Debug.Log("3 seconds have passed, now resetting timer.");
rigidbody.useGravity = true;
timer = 0;
}
if((timer >= 1.25) && (rigidbody.useGravity = true))
{
// Waits for the item to hit the ground and then resets it
Debug.Log("1 seconds have passed, now resetting timer.");
rigidbody.useGravity = false;
timer = 0;
transform.Translate(0,5,0);
}
}
}
The comments explain most of what the code is supposed to do, essentially just use Time.deltaTime to create a timer that will alternate between waiting approximately 5 seconds to remove gravity and make the object fall and waiting approximately 1 second to let the object fall to the ground and then resetting said object. For some reason, the code only wants to execute the second if statement, so I'm guessing something is wrong with the rigidbody.useGravity variable. I'm a little new to coding.
Change value assignment to a conditional.
public class FallingObject : MonoBehaviour
{
// Variables
float timer = 0;
MeshRenderer renderer;
Rigidbody rigidbody;
// Start is called before the first frame update
void Start()
{
// Cached References
renderer = GetComponent<MeshRenderer>();
rigidbody = GetComponent<Rigidbody>();
rigidbody.useGravity = false;
}
// Update is called once per frame
void Update()
{
// Setup to make a timer work every 5 seconds
timer = timer + Time.deltaTime;
//Here is where you'd get rid of the value assignment.
if((timer >= 6) && (rigidbody.useGravity == false))
{
// Makes the item fall after 3 seconds
Debug.Log("3 seconds have passed, now resetting timer.");
rigidbody.useGravity = true;
timer = 0;
}
//Here is where you'd get rid of the value assignment.
if((timer >= 1.25) && (rigidbody.useGravity == true))
{
// Waits for the item to hit the ground and then resets it
Debug.Log("1 seconds have passed, now resetting timer.");
rigidbody.useGravity = false;
timer = 0;
transform.Translate(0,5,0);
}
}
}
If the boolean is not null-able or a three-state then you can also write it like this.
...
if((timer >= 6) && !rigidbody.useGravity)
{
...
...
if((timer >= 1.25) && rigidbody.useGravity)
{
...
Visual Studio Green Squiggles Warning article I was talking about in the comment.

Unity - deleting a specific gameobject when mouse/pointer is over it

I am creating a virtual reality game where when you double click on an object it deletes it. However multiple objects are duplicates of eachother so when i attach my double click script to them it will delete all the objects upon double click. I want it to just delete the one the mouse is on. I will attach my script below:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class doubleClick : MonoBehaviour
{
private float firstClickTime, timebetweenClicks;
private bool coroutineAllowed;
private int clickCounter;
public GameObject toDelete;
// Start is called before the first frame update
void Start()
{
firstClickTime = 0f;
timebetweenClicks = 0.2f;
clickCounter = 0;
coroutineAllowed = true;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonUp(0))
clickCounter += 1;
if (clickCounter == 1 && coroutineAllowed)
{
firstClickTime = Time.time;
StartCoroutine(DoubleClickDetection());
}
}
private IEnumerator DoubleClickDetection()
{
coroutineAllowed = false;
while (Time.time < firstClickTime + timebetweenClicks)
{
if (clickCounter == 2)
{
//Destroy(toDelete);
break;
}
yield return new WaitForEndOfFrame();
}
clickCounter = 0;
firstClickTime = 0f;
coroutineAllowed = true;
}
}
I can't see anything that jumps out in your code. Padia's answer is on the right track, though. Mouse input handling when you want to interact with objects is best done from within that object/prefab. That way, you're guaranteed that only that object is interacted with. If not, then there's likely something else going on with your code.
Unfortunately, it's a little late for me to work out a complete solution. But here's a possible solution.
Within the prefab's code, insert an OnMouseDown function. In that function, check if the double-click timer's been started. If not, set a flag to tell the prefab that the double-click timer needs to start (call it WaitingForTimerStart). You could alternatively use an enum to hold the timer state. In any event, don't start the timer yet.
Within the prefab's code, insert an OnMouseUp function. That should check if the timer start flag's (WaitingForTimerStart) been set. If it has, set another timer flag to tell it to run the timer (RunTimer).
In the prefab's Update function, run the timer. I'm sure you know what to do here.
In the prefab's OnMouseDown function (the one you added earlier), check if the timer's running. If it is, then you know a double-click's been performed. Destroy the object.
This way, there's no need to check names, use raycasting or coroutines. Each object will have its own timer and be fully independent of each other.
One main issue with your code is: You are starting the Coroutine everyframe!
You have to wrap your code block in { } after the if, otherwise the condition only applies for the one line after it!
Instead of
if (Input.GetMouseButtonUp(0))
clickCounter += 1;
if (clickCounter == 1 && coroutineAllowed)
{
firstClickTime = Time.time;
StartCoroutine(DoubleClickDetection());
}
it should probably rather be
if (Input.GetMouseButtonUp(0))
{
clickCounter += 1;
if (clickCounter == 1 && coroutineAllowed)
{
firstClickTime = Time.time;
StartCoroutine(DoubleClickDetection());
}
}
Then
I want it to just delete the one the mouse is on.
Well currently you are using Input.GetMouseButtonUp which is true global in the entire app, not only the object the mouse is currently over.
You can rather use e.g. OnMouseDown which is called when the mouse goes down over a collider or UI element.
private void OnMouseDown ()
{
clickCounter += 1;
if (clickCounter == 1 && coroutineAllowed)
{
firstClickTime = Time.time;
StartCoroutine(DoubleClickDetection());
}
}
Try this code:
private float firstClickTime, timebetweenClicks;
private bool coroutineAllowed;
private int clickCounter;
RaycastHit hit;
// Start is called before the first frame update
void Start()
{
firstClickTime = 0f;
timebetweenClicks = 0.2f;
clickCounter = 0;
coroutineAllowed = true;
}
private void OnMouseUp()
{
clickCounter += 1;
}
// Update is called once per frame
void Update()
{
if (clickCounter == 1 && coroutineAllowed)
{
firstClickTime = Time.time;
StartCoroutine(DoubleClickDetection());
}
}
private IEnumerator DoubleClickDetection()
{
coroutineAllowed = false;
while (Time.time < firstClickTime + timebetweenClicks)
{
if (clickCounter == 2)
{
if (Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
{
if (hit.collider.transform == this.transform)
{
Destroy(this.gameObject);
}
}
break;
}
yield return new WaitForEndOfFrame();
}
clickCounter = 0;
firstClickTime = 0f;
coroutineAllowed = true;
}
This code use OnMouseDown() Unity function to detect when the game object is clicked by the mouse, and add 1 to the clickCounter variable.
Also you can use OnMouseUp() function if you prefer to detect the click when the mouse is up.

Not cycling through an array as expected

I'm trying to get the player to continue on after he jumps (see code), but what he does is return back to the jumpPosition transform without continuing on to the next point.
Here is what it is doing in Unity:
...
Here is my code for playerMovment:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class MovementController : MonoBehaviour
{
// public GameObject playerToMove; // not sure why I need this
public float moveSpeed; // move speed of the player going from player postion to current point, possible to use somewhere else
private Transform currentPoint; // used to determine where the next point the player has to move by cycling through 'points' array
public Transform jumpPoint; // used as a location trigger to tell the player when to jump -- will be attempting to make into an array
public Transform crouchPoint; // used as a location trigger to tell the player when to crounch -- will be attempting to make into an array
public Transform[] points; // an array of location for the 'currentPoint' to cycle through
public float maxPause = 100; // used to determine the length of time between when the player arrives at the 'currentPoint' and when to leave said point; default = 100
public float reducedPause = 2; // used to set 'maxPause' to a smaller number so that player won't keep jumping/crouching
public TestCharacterController2D controller; // acceses the TestCharacterController2D script (I didnt write this script but plan to modiify) used for basic move, jump, and crouch funtions
public Animator animator; // my attempt to find the player's animator
public bool isRight; // used to to determine which way the character is facing -- I think this can be accesed through the 'controller' variable (TestCharacterController2D script)
private bool jump; // to tell the 'controller' when to jump
private bool crouch; // to tell the 'controller' when to crouch
private bool pause = false; // used to determine when the player arrives at the 'currentPoint' and the 'maxPause' countdown begins
public int pointsSelection; // used to cycle the 'points' array when maxPause cycle is over and player is at current point
// public float jumpHeight = 100f; // not sure why used
void Start() // looking into 'onAwake' maybe? (or others)
{
currentPoint = points[pointsSelection]; // sets currentPoint to default location ('pointSelection' is 'publc' so can be modified in Unity
isRight = true; // player starts facing right -- as per character animations
}
void Update() // not sure if should have more in 'FixedUpdate' or others (maybe?)
{
jump = false;
if (Vector2.Distance(transform.position, currentPoint.position) < 0.05f)
// checks to see if player is at 'currentPoint'
{
pause = true; // starts the pause sequenece
Debug.Log("Pause = " + pause);
if (pause) // when the movement is pause do the the following
{
moveSpeed = 0;
animator.SetFloat("Speed", 0); // player stops moving -- works!
if (maxPause <= 100) // checks to see if still paused
{
Debug.Log("this is maxPause: " + maxPause);
if (maxPause < 0) // found 'maxPause' was going to far below zero
maxPause = 0;
maxPause--; // reduce pause amount (working way out of loop)
}
if (maxPause == 0) // when 'maxPause' timer has finished
{
pointsSelection++; // move to next point
maxPause = 100; // reset 'maxPause' timer
pause = false; // resume 'transform.position == currentPoint.position' process
}
}
if (pointsSelection == points.Length) // makes sure 'pointsSelection' doesn't go out of bounds
{
Debug.Log("at end of array");
pointsSelection = 0; // start the player's movement process over again
}
}
else // not sure if requried
{
Debug.Log("pause = false");
Debug.Log("this is the moveSpeed " + moveSpeed);
Debug.Log("pointsSelection: " + pointsSelection);
}
if (Vector2.Distance(transform.position, jumpPoint.position) < 0.05f && jumpPoint == currentPoint) // conditions for the jump action (automatic) -- I fell the whole thing needs to be more elaborate ** WORK IN PROGRESS **
{
jump = true;
}
else
jump = false;
currentPoint = points[pointsSelection]; // moved to line 130 -- not sure if better here
}
void FixedUpdate()
{
if (isRight && transform.position.x > currentPoint.position.x) // flipping the character -- I'm pretty sure I can use TestCharacterController2D to do this for me, this is comparing the player's 'transform'
{
moveSpeed = -0.25f; // tells controller to head in the left direction
isRight = false; // no longer facing right
}
if (!isRight && transform.position.x < currentPoint.position.x) // reverse of above
{
moveSpeed = 0.25f; // tells controller to head in the right direction
isRight = true; // no longer facing left
}
if (moveSpeed > 0 || moveSpeed < 0)
animator.SetFloat("Speed", 1); // player starts PlayerRun animation -- works!
// Move our character
controller.Move(moveSpeed, crouch, jump); // draws from the TestCharacterController2D script
}
public void OnLanding()
{
animator.SetBool("Jumped", false);
}
}

How can I wait number of seconds before changing for new random speed? [duplicate]

This question already has answers here:
How to make the script wait/sleep in a simple way in unity
(7 answers)
Closed 4 years ago.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GateControl : MonoBehaviour
{
public Transform door;
public float doorSpeed = 1.0f;
public bool randomDoorSpeed = false;
[Range(0.3f, 10)]
public float randomSpeedRange;
private Vector3 originalDoorPosition;
// Use this for initialization
void Start()
{
originalDoorPosition = door.position;
}
// Update is called once per frame
void Update()
{
if (randomDoorSpeed == true && randomSpeedRange > 0.3f)
{
StartCoroutine(DoorSpeedWaitForSeconds());
}
door.position = Vector3.Lerp(originalDoorPosition,
new Vector3(originalDoorPosition.x, originalDoorPosition.y, 64f),
Mathf.PingPong(Time.time * doorSpeed, 1.0f));
}
IEnumerator DoorSpeedWaitForSeconds()
{
doorSpeed = Random.Range(0.3f, randomSpeedRange);
yield return new WaitForSeconds(3);
}
}
Making StartCoroutine inside the Update is a bad idea. But I want that it will take one random speed when running the game then will wait 3 seconds and change to a new random speed then wait another 3 seconds and change for another new random speed and so on.
And while it's waiting 3 seconds to keep the current speed constant until the next change.
Update:
This is what I tried:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GateControl : MonoBehaviour
{
public Transform door;
public float doorSpeed = 1.0f;
public bool randomDoorSpeed = false;
public bool IsGameRunning = false;
[Range(0.3f, 10)]
public float randomSpeedRange;
private Vector3 originalDoorPosition;
// Use this for initialization
void Start()
{
IsGameRunning = true;
originalDoorPosition = door.position;
StartCoroutine(DoorSpeedWaitForSeconds());
}
// Update is called once per frame
void Update()
{
door.position = Vector3.Lerp(originalDoorPosition,
new Vector3(originalDoorPosition.x, originalDoorPosition.y, 64f),
Mathf.PingPong(Time.time * doorSpeed, 1.0f));
}
IEnumerator DoorSpeedWaitForSeconds()
{
var delay = new WaitForSeconds(3);//define ONCE to avoid memory leak
while (IsGameRunning)
{
if (randomDoorSpeed == true && randomSpeedRange > 0.3f)
doorSpeed = Random.Range(0.3f, randomSpeedRange);
yield return delay;
}
}
}
But there are two problems.
The first problem is that every 3 seconds, when it's changing the speed of the door, it's also changing the door position from its current position. So it looks like the door position is jumping to another position and then continue from there. How can I make that it will change the speed meanwhile the door keep moving from its current position ?
Second problem is how can I change the randomDorrSpeed flag so it will take effect while the game is running? I Want that if randomDorrSpeed is false use the original speed of the door (1.0) and if it`s true use the random speed.
You already know that the coroutine should start from Start:
void Start()
{
//initialization
StartCoroutine(DoorSpeedWaitForSeconds());
}
So make the coroutine a loop with the proper terminate condition:
IEnumerator DoorSpeedWaitForSeconds()
{
var delay = new WaitForSeconds(3);//define ONCE to avoid memory leak
while(IsGameRunning)
{
if(randomDoorSpeed == true && randomSpeedRange > 0.3f)
doorSpeed = Random.Range(0.3f, randomSpeedRange);
if(!randomDoorSpeed)
doorSpeed = 1;//reset back to original value
yield return delay;//wait
}
}
For the other question you asked, if you think about it you can't possibly use ping pong with dynamic speed based on Time.time. You need to change it like this:
bool isRising = true;
float fraq = 0;
void Update()
{
if (isRising)
fraq += Time.deltaTime * doorSpeed;
else
fraq -= Time.deltaTime * doorSpeed;
if (fraq >= 1)
isRising = false;
if (fraq <= 0)
isRising = true;
fraq = Mathf.Clamp(fraq, 0, 1);
door.position = Vector3.Lerp(originalDoorPosition,
new Vector3(originalDoorPosition.x, originalDoorPosition.y, 64f),
fraq);
}
You can solve the original problem without coroutines:
public float timeBetweenChangeSpeed = 3f;
public float timer = 0;
void Update ()
{
// Add the time since Update was last called to the timer.
timer += Time.deltaTime;
// If 3 seconds passed, time to change speed
if(timer >= timeBetweenChangeSpeed)
{
timer = 0f;
//Here you call the function to change the random Speed (or you can place the logic directly)
ChangeRandomSpeed();
}
}
And about opening and closing doors. Here is a script I used to control doors in a maze game I worked in:
You need to set empty gameObjects with to set the boundaries, that is until what point you want to move the door one opening or when closing. You place this empty gameobjects in your scene and link them to the scrip in the correct field. The script will take the transform.position component on it's own. There is also a trigger enter to activate the door when a character approaches. If you dont need that part, I can edit the code tomorrow.
You can use this script also to move platforms, enemies... in general anything which can move in a straight line.
using UnityEngine;
using System.Collections;
public class OpenDoor : MonoBehaviour {
// define the possible states through an enumeration
public enum motionDirections {Left,Right};
// store the state
public motionDirections motionState = motionDirections.Left;
//Variables for State Machine
bool mOpening = false;
bool mClosing = false;
//bool mOpened = false;
//OpenRanges to open/close the door
public int OpenRange = 5;
public GameObject StopIn;
public GameObject StartIn;
//Variables for Movement
float SpeedDoor = 8f;
float MoveTime = 0f;
int CounterDetections = 0;
void Update () {
// if beyond MoveTime, and triggered, perform movement
if (mOpening || mClosing) {/*Time.time >= MoveTime && */
Movement();
}
}
void Movement()
{
if(mOpening)
{
transform.position = Vector3.MoveTowards(transform.position, StopIn.transform.position, SpeedDoor * Time.deltaTime);
if(Vector3.Distance(transform.position, StopIn.transform.position) <= 0)
mOpening = false;
}else{ //This means it is closing
transform.position = Vector3.MoveTowards(transform.position, StartIn.transform.position, SpeedDoor * Time.deltaTime);
if(Vector3.Distance(transform.position, StartIn.transform.position) <= 0)
mClosing = false;
}
}
// To decide if door should be opened or be closed
void OnTriggerEnter(Collider Other)
{
print("Tag: "+Other.gameObject.tag);
if(Other.gameObject.tag == "Enemy" || Other.gameObject.tag == "Player" || Other.gameObject.tag == "Elevator")
{
CounterDetections++;
if(!mOpening)
Opening();
}
}
void OnTriggerStay(Collider Other)
{
if(Other.gameObject.tag == "Elevator")
{
if(!mOpening)
Opening();
}
}
void OnTriggerExit(Collider Other)
{
if(Other.gameObject.tag == "Enemy" || Other.gameObject.tag == "Player")
{
CounterDetections--;
if(CounterDetections<1)
Closing();
}
}
void Opening()
{
mOpening = true;
mClosing = false;
}
void Closing()
{
mClosing = true;
mOpening = false;
}
}
Using timer and setting an interval. The delegate event will fire every time the interval is reached.
var t = new Timer {Interval = 3000};
t.Elapsed += (sender, args) => { /* code here */};

Unity How to make a gameobject going through waypoints endlessly?

I have this code:
using UnityEngine;
using UnityEngine.AI;
using System.Collections;
public class AutoPilot : MonoBehaviour {
public Transform[] points;
private int destPoint = 0;
private NavMeshAgent agent;
void Start () {
agent = GetComponent<NavMeshAgent>();
// Disabling auto-braking allows for continuous movement
// between points (ie, the agent doesn't slow down as it
// approaches a destination point).
GotoNextPoint();
}
void GotoNextPoint() {
// Returns if no points have been set up
if (points.Length == 0)
return;
// Set the agent to go to the currently selected destination.
agent.destination = points[destPoint].transform.position;
// Choose the next point in the array as the destination,
// cycling to the start if necessary.
destPoint = (destPoint + 1) % points.Length;
}
void Update () {
// Choose the next destination point when the agent gets
// close to the current one.
if (!agent.pathPending && agent.remainingDistance < 2f)
GotoNextPoint();
}
}
Where I go through my waypoints and the agen follows them, but when I am at the last waypoint, how to make it restart itslef? to keep going?
Is it possible to reset somehow or what is the best way?
I fixed it by adding this:
if (destPoint == points.Length) {
destPoint = 0;
}

Categories