- Home /
Rotate, follow randomly generted waypoints?
How can I script an object that rotates while following a randomly generated waypoint?
Hello, I'm quite new to Unity and after searching quite a bit around the forums, I decided to place a question.
I already found a script made by spinaljack, which serves as the waypoint following bit. Only problem I have is regarding the turning part. I wanted it to turn and move(forward ofc), when the new waypoint was generated. I already tried playing around with quaternions and its rotation methods, but the object in question keeps moving forward for some reason when I try to. EDIT: I realized I did not explain clearly enough that I only want the object to rotate when the new waypoint is created, to show that it is turning, rather that just locking-on to the next point.
Here's the code I got from spinaljack, the commented parts are my attempt to include the rotation:
#pragma strict
var Speed = 5;
var wayPoint : Vector3;
var rotation;
//values that will be set in the Inspector
//var RotationSpeed:float = 5;
//values for internal use
//var _lookRotation:Quaternion;
//var _direction:Vector3;
function Start(){
//initialise the target way point
Wander();
}
function Update()
{
//find the vector pointing from our position to the target
//_direction = wayPoint;
//(target.position - transform.position).normalized;
//create the rotation we need to be in to look at the target
//_lookRotation = Quaternion.LookRotation(_direction);
//rotate us over time according to speed until we are in the required rotation
//transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, Time.deltaTime * RotationSpeed);
// this is called every frame
// do move code here
transform.position += transform.TransformDirection(Vector3.forward)*Speed*Time.deltaTime;
if((transform.position - wayPoint).magnitude < 3)
{
// when the distance between us and the target is less than 3
// create a new way point target
Wander();
}
}
function Wander()
{
// does nothing except pick a new destination to go to
wayPoint= Random.insideUnitSphere *47;
wayPoint.y = 1;
// don't need to change direction every frame seeing as you walk in a straight line only
transform.LookAt(wayPoint);
Debug.Log(wayPoint + " and " + (transform.position - wayPoint).magnitude);
}
Thanks in advance.
Is there an example of the functionality you want out that you can point to? I am still having difficulty understanding what you want. I cannot tell if you simply want the object to orient itself to face the next waypoint (standard waypoint following), to only orient itself/move to the waypoint upon it's creation (idling until a new waypoint is generated), or something else entirely.
Perhaps looking at this might be useful?: http://wiki.unity3d.com/index.php?title=SeekSteer
Do you want it to rotate to point at the new waypoint before it starts moving?
@Argylelabcoat $$anonymous$$y main focus was to make the object follow the randomly generated waypoint(it generates a new one each time the object is closer than 3 units to the current waypoint, so the object theoretically never stops moving as long as there are new waypoints) and when it detects a new one, it would slowly rotate towards it until it was facing it and so on.
@Screenhog $$anonymous$$y idea was to let it continue it's forward motion when rotating, to give the impression of smooth turning, rather than just stop and turn.
Thank you for the feedback
Have you looked at iTween yet? With iTween.$$anonymous$$oveTo, you can choose a location and have a unit move to it while pointing in that direction.
Answer by phodges · Oct 20, 2012 at 08:35 AM
I'll bite. I set up a very simple 2D steering behaviour in a test scene. Here's what I put into it:
A wanderer object, assigning it a capsule so that I could follow its motion.
A target object, assigning it a cube.
I placed these two objects on a plane and then positioned the camera so that I could easily watch the show
Attached my simple script to the wanderer object and set its 'Target' property to the target object
There's nothing special about my using a target object, this was purely for visualisation. You could just as easily do this with just a vector and plot that if you need to. The script is written in C# and I'll paste it below:
using UnityEngine;
using System.Collections;
public class Wanderer : MonoBehaviour {
// I assign this to a test object in my scene so as to have a clear destination marker.
public GameObject target = null;
// Used for min/max positioning of the target.
public Vector2 wanderLimits = new Vector2(10f,10f);
// Smoothly turn at this maximum rate to face targets.
public float maxTurningSpeed = 360f;
// Maximum speed of motion
public float maxSpeed = 10f;
// Smooth motion as we approach targets and move to new ones.
public float acceleration = 3f;
// Slow down once we come close to the target
public float proximityRadius = 3f;
// When we're this close we'll pick a new target
public float arrivalRadius = 1f;
// Current speed
float speed = 0f;
// Use this for initialization
void Start () {
SelectNewPoint();
}
// Update is called once per frame
void Update () {
// Find the relative vector from our current position to the target.
// We're doing all of this in 2D, so we scrub any vertical components in calculation
Vector3 relative = GetTargetPoint() - transform.position;
relative.y = 0f;
bool turned = false;
// Do we need to adjust facing?
Quaternion idealFacing = Quaternion.LookRotation(relative);
// This is how far we would like to turn
float angle = Quaternion.Angle(transform.rotation, idealFacing);
// This is most we are allowed to turn this frame
float maxTurn = maxTurningSpeed * Time.deltaTime;
if (maxTurn >= angle){
// Excellent. We can just face the target
transform.rotation = idealFacing;
}else{
// We'll have to take this more gradually then; use slerp to smoothly face the target.
transform.rotation = Quaternion.Slerp(transform.rotation, idealFacing, maxTurn / angle);
turned = true;
}
// Now that we've adjusted facing, let's move our wanderer around
if (turned){
// If we needed to turn then slow down while we correct course, bringing ourselves to a halt if necessary.
speed = Mathf.Max(0f, speed - acceleration * Time.deltaTime);
}else{
// Since we didn't turn we will speed up if the target is far away and slow down otherwise
float distance = relative.magnitude;
if (distance > proximityRadius){
speed = Mathf.Min(maxSpeed, speed + acceleration * Time.deltaTime);
}else{
float frac = distance / proximityRadius;
float idealSpeed = maxSpeed * frac;
speed = Mathf.Max(idealSpeed, speed - acceleration * Time.deltaTime);
}
// Close enough? Then go somewhere else.
if (distance <= arrivalRadius){
SelectNewPoint();
}
}
// Move.
transform.position += transform.forward * speed * Time.deltaTime;
}
void SelectNewPoint(){
if (null != target){
Vector3 pos = target.transform.position;
pos.x = (Random.value - 0.5f) * 2f * wanderLimits.x;
pos.z = (Random.value - 0.5f) * 2f * wanderLimits.y;
target.transform.position = pos;
}else{
Debug.LogError("Where is my target?");
}
}
Vector3 GetTargetPoint(){
Vector3 result = Vector3.zero;
if (null != target){
result = target.transform.position;
}else{
Debug.LogError("Where is my target?");
}
return result;
}
}
Thank you, this was precisely what I was trying to do. I'll be sure to study it and complete it's behaviour like I was trying to do.
Answer by BerggreenDK · Oct 19, 2012 at 09:33 PM
I would:
First make an null object that facing "north" anytime. This object I would make follow my waypoint.
Secondly, as a child object I would place the rotating object at 0,0,0 of the other object, so that could be doing a simple transform.rotate(what ever axis and speed)
Your answer
Follow this Question
Related Questions
Character Controller slides sideways when it hits objects are angles different from 90 degrees 1 Answer
Player Going Backwards on Waypoint Path Issue 0 Answers
click to move workig script!! but pls help with rotation!! :( 1 Answer
How to make a RigidBody not go into ground when tilted foward? 2 Answers
Undesirable character flipping 0 Answers