Hi, i have a rollerball npc i want to follow a waypointTargetSystem, i made the sphere following the waypointTargetSystem but it always follow it the same way.
Wwhat i mean it dosnt wanderer left or right of it. so if i use 2 or 3 on same waypointTargetSystem and
1 goes faster they crash into each other so i want them to wander a little random to the left or right of the waypointTargetSystem.
i tried used mathf.clamp but i cant get it to work, can anyone look at my script and put me in a right direction
Just want to add if u need this script it works with the build in unity WaypointTargetSystem so feel free to copy paste it for you own use. It follows the waypointTargetSystem with curves and everything but as my problem is, it dont wander yet.
here is my script;
using UnityEngine;
public class RollerBallNpc: MonoBehaviour
{
public Transform m_Target;
private Rigidbody m_Rigidbody;
public float m_MaxAngularVelocity = 10;
// Use this for initialization
void Awake()
{
m_Rigidbody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate()
{
Vector3 normalizedDirection = (m_Target.transform.position - m_Rigidbody.transform.position).normalized;
m_Rigidbody.velocity = new Vector3(normalizedDirection.x * m_MaxAngularVelocity, -5, normalizedDirection.z * m_MaxAngularVelocity);
}
// y axis is set to minus to put it to the ground if you going downhill,
// change it for more preasure if needed.
public void SetTarget(Transform WaypointTargetObject)
{
m_Target = WaypointTargetObject;
}
}
I recommend formatting your posts a bit better, and using the code tags to add code to a post, as it is currently very unreadable and as such is unlikely to attract help.
public void SetTarget(Transform WaypointTargetObject)
{
m_Target = WaypointTargetObject;
//add in a random verable to make the NPC not go directly to the waypoint
float X = new Random.Range(-10.0f, 10.0f);
float Y = new Random.Range(-10.0f, 10.0f);
float Z = new Random.Range(-10.0f, 10.0f);
m_Target.position.x += X;
m_Target.position.y += Y;
m_Target.position.z += Z;
}
using UnityEngine;
public class RollerBallNpc : MonoBehaviour
{
public Transform m_Target;
private Rigidbody m_Rigidbody;
public float m_MaxAngularVelocity = 10;
// Use this for initialization
void Awake()
{
m_Rigidbody = GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate()
{
Vector3 normalizedDirection = (m_Target.transform.position - m_Rigidbody.transform.position).normalized;
m_Rigidbody.velocity = new Vector3(normalizedDirection.x * m_MaxAngularVelocity, -5, normalizedDirection.z * m_MaxAngularVelocity);
}
public void SetTarget(Transform WaypointTargetObject)
{
m_Target = WaypointTargetObject;
//add in a random verable to make the NPC not go directly to the waypoint
float X = new Random.Range(-10.0f, 10.0f);
float Y = new Random.Range(-10.0f, 10.0f);
float Z = new Random.Range(-10.0f, 10.0f);
m_Target.position.x += X;
m_Target.position.y += Y;
m_Target.position.z += Z;
}
}
but i get alot of errors new Random.Range dont work but if i remove new i get no errors but
m_Target.position.x += X;
m_Target.position.y += Y;
m_Target.position.z += Z;
get errors also cannot modify the return value of ‘transform.position’ because it is not a variable.
Anyone now how i can fix this?
ummm
try to add UnityEngine in frount of Randome.Range
float X = new UnityEngine.Random.Range(-10.0f, 10.0f);
float Y = new UnityEngine.Random.Range(-10.0f, 10.0f);
float Z = new UnityEngine.Random.Range(-10.0f, 10.0f);
yah, that didn’t work, So i worked on the code. Here is my updated code, with no errors on my side
public void SetTarget(Transform WaypointTargetObject)
{
m_Target = WaypointTargetObject;
//add in a random verable to make the NPC not go directly to the waypoint
float X = Random.Range(-10.0f, 10.0f);
float Y = Random.Range(-10.0f, 10.0f);
float Z = Random.Range(-10.0f, 10.0f);
m_Target.position = m_Target.position + new Vector3(X, Y, Z);
}
ok thx for the replies but i have to spheres to test this with and they are following the WaypointTargetSystem but they are still following it presicely the same route, no one going left or right, is it something i do wrong? add full script to the sphere make empty gameobject a child of the sphere, this gameobject i drag into the target on the script. Also for the waypoint script i use unity standard i copy the script here
using System;
using UnityEngine;
namespace UnityStandardAssets.Utility
{
public class WaypointProgressTracker : MonoBehaviour
{
// This script can be used with any object that is supposed to follow a
// route marked out by waypoints.
// This script manages the amount to look ahead along the route,
// and keeps track of progress and laps.
[SerializeField] private WaypointCircuit circuit; // A reference to the waypoint-based route we should follow
[SerializeField] private float lookAheadForTargetOffset = 5;
// The offset ahead along the route that the we will aim for
[SerializeField] private float lookAheadForTargetFactor = .1f;
// A multiplier adding distance ahead along the route to aim for, based on current speed
[SerializeField] private float lookAheadForSpeedOffset = 10;
// The offset ahead only the route for speed adjustments (applied as the rotation of the waypoint target transform)
[SerializeField] private float lookAheadForSpeedFactor = .2f;
// A multiplier adding distance ahead along the route for speed adjustments
[SerializeField] private ProgressStyle progressStyle = ProgressStyle.SmoothAlongRoute;
// whether to update the position smoothly along the route (good for curved paths) or just when we reach each waypoint.
[SerializeField] private float pointToPointThreshold = 4;
// proximity to waypoint which must be reached to switch target to next waypoint : only used in PointToPoint mode.
public enum ProgressStyle
{
SmoothAlongRoute,
PointToPoint,
}
// these are public, readable by other objects - i.e. for an AI to know where to head!
public WaypointCircuit.RoutePoint targetPoint { get; private set; }
public WaypointCircuit.RoutePoint speedPoint { get; private set; }
public WaypointCircuit.RoutePoint progressPoint { get; private set; }
public Transform target;
private float progressDistance; // The progress round the route, used in smooth mode.
private int progressNum; // the current waypoint number, used in point-to-point mode.
private Vector3 lastPosition; // Used to calculate current speed (since we may not have a rigidbody component)
private float speed; // current speed of this object (calculated from delta since last frame)
// setup script properties
private void Start()
{
// we use a transform to represent the point to aim for, and the point which
// is considered for upcoming changes-of-speed. This allows this component
// to communicate this information to the AI without requiring further dependencies.
// You can manually create a transform and assign it to this component *and* the AI,
// then this component will update it, and the AI can read it.
if (target == null)
{
target = new GameObject(name + " Waypoint Target").transform;
}
Reset();
}
// reset the object to sensible values
public void Reset()
{
progressDistance = 0;
progressNum = 0;
if (progressStyle == ProgressStyle.PointToPoint)
{
target.position = circuit.Waypoints[progressNum].position;
target.rotation = circuit.Waypoints[progressNum].rotation;
}
}
private void Update()
{
if (progressStyle == ProgressStyle.SmoothAlongRoute)
{
// determine the position we should currently be aiming for
// (this is different to the current progress position, it is a a certain amount ahead along the route)
// we use lerp as a simple way of smoothing out the speed over time.
if (Time.deltaTime > 0)
{
speed = Mathf.Lerp(speed, (lastPosition - transform.position).magnitude/Time.deltaTime,
Time.deltaTime);
}
target.position =
circuit.GetRoutePoint(progressDistance + lookAheadForTargetOffset + lookAheadForTargetFactor*speed)
.position;
target.rotation =
Quaternion.LookRotation(
circuit.GetRoutePoint(progressDistance + lookAheadForSpeedOffset + lookAheadForSpeedFactor*speed)
.direction);
// get our current progress along the route
progressPoint = circuit.GetRoutePoint(progressDistance);
Vector3 progressDelta = progressPoint.position - transform.position;
if (Vector3.Dot(progressDelta, progressPoint.direction) < 0)
{
progressDistance += progressDelta.magnitude*0.5f;
}
lastPosition = transform.position;
}
else
{
// point to point mode. Just increase the waypoint if we're close enough:
Vector3 targetDelta = target.position - transform.position;
if (targetDelta.magnitude < pointToPointThreshold)
{
progressNum = (progressNum + 1)%circuit.Waypoints.Length;
}
target.position = circuit.Waypoints[progressNum].position;
target.rotation = circuit.Waypoints[progressNum].rotation;
// get our current progress along the route
progressPoint = circuit.GetRoutePoint(progressDistance);
Vector3 progressDelta = progressPoint.position - transform.position;
if (Vector3.Dot(progressDelta, progressPoint.direction) < 0)
{
progressDistance += progressDelta.magnitude;
}
lastPosition = transform.position;
}
}
private void OnDrawGizmos()
{
if (Application.isPlaying)
{
Gizmos.color = Color.green;
Gizmos.DrawLine(transform.position, target.position);
Gizmos.DrawWireSphere(circuit.GetRoutePosition(progressDistance), 1);
Gizmos.color = Color.yellow;
Gizmos.DrawLine(target.position, target.position + target.forward);
}
}
}
}
anyone got an idea why it wont work?
all help is appreciated.
So this really means following the the waypoints from point0 to point1… point2… point3. and then you have a second NPC that follows it in the opposite direction. point3, point2, point1, point0
I’ve added a bool pathFwd and an if statement to change the progressNum
using System;
using UnityEngine;
namespace UnityStandardAssets.Utility
{
public class WaypointProgressTracker : MonoBehaviour
{
// This script can be used with any object that is supposed to follow a
// route marked out by waypoints.
// This script manages the amount to look ahead along the route,
// and keeps track of progress and laps.
[SerializeField] private WaypointCircuit circuit; // A reference to the waypoint-based route we should follow
[SerializeField] private float lookAheadForTargetOffset = 5;
// The offset ahead along the route that the we will aim for
[SerializeField] private float lookAheadForTargetFactor = .1f;
// A multiplier adding distance ahead along the route to aim for, based on current speed
[SerializeField] private float lookAheadForSpeedOffset = 10;
// The offset ahead only the route for speed adjustments (applied as the rotation of the waypoint target transform)
[SerializeField] private float lookAheadForSpeedFactor = .2f;
// A multiplier adding distance ahead along the route for speed adjustments
[SerializeField] private ProgressStyle progressStyle = ProgressStyle.SmoothAlongRoute;
// whether to update the position smoothly along the route (good for curved paths) or just when we reach each waypoint.
[SerializeField] private float pointToPointThreshold = 4;
// proximity to waypoint which must be reached to switch target to next waypoint : only used in PointToPoint mode.
[SerializeField] private bool pathFwd;
// direction to follow
public enum ProgressStyle
{
SmoothAlongRoute,
PointToPoint,
}
// these are public, readable by other objects - i.e. for an AI to know where to head!
public WaypointCircuit.RoutePoint targetPoint { get; private set; }
public WaypointCircuit.RoutePoint speedPoint { get; private set; }
public WaypointCircuit.RoutePoint progressPoint { get; private set; }
public Transform target;
private float progressDistance; // The progress round the route, used in smooth mode.
private int progressNum; // the current waypoint number, used in point-to-point mode.
private Vector3 lastPosition; // Used to calculate current speed (since we may not have a rigidbody component)
private float speed; // current speed of this object (calculated from delta since last frame)
// setup script properties
private void Start()
{
if(UnityEngine.Random.Range(0, 2) == 0) //randomly set the bool
{
pathFwd = true;
}
else
{
pathFwd = false;
}
// we use a transform to represent the point to aim for, and the point which
// is considered for upcoming changes-of-speed. This allows this component
// to communicate this information to the AI without requiring further dependencies.
// You can manually create a transform and assign it to this component *and* the AI,
// then this component will update it, and the AI can read it.
if (target == null)
{
target = new GameObject(name + " Waypoint Target").transform;
}
Reset();
}
// reset the object to sensible values
public void Reset()
{
progressDistance = 0;
progressNum = 0;
if (progressStyle == ProgressStyle.PointToPoint)
{
target.position = circuit.Waypoints[progressNum].position;
target.rotation = circuit.Waypoints[progressNum].rotation;
}
}
private void Update()
{
if (progressStyle == ProgressStyle.SmoothAlongRoute)
{
// determine the position we should currently be aiming for
// (this is different to the current progress position, it is a a certain amount ahead along the route)
// we use lerp as a simple way of smoothing out the speed over time.
if (Time.deltaTime > 0)
{
speed = Mathf.Lerp(speed, (lastPosition - transform.position).magnitude / Time.deltaTime,
Time.deltaTime);
}
target.position =
circuit.GetRoutePoint(progressDistance + lookAheadForTargetOffset + lookAheadForTargetFactor * speed)
.position;
target.rotation =
Quaternion.LookRotation(
circuit.GetRoutePoint(progressDistance + lookAheadForSpeedOffset + lookAheadForSpeedFactor * speed)
.direction);
// get our current progress along the route
progressPoint = circuit.GetRoutePoint(progressDistance);
Vector3 progressDelta = progressPoint.position - transform.position;
if (Vector3.Dot(progressDelta, progressPoint.direction) < 0)
{
progressDistance += progressDelta.magnitude * 0.5f;
}
lastPosition = transform.position;
}
else
{
// point to point mode. Just increase the waypoint if we're close enough:
Vector3 targetDelta = target.position - transform.position;
if (targetDelta.magnitude < pointToPointThreshold)
{
if(pathFwd)
{
//forward on the path
progressNum = (progressNum + 1) % circuit.Waypoints.Length;
}
else
{
//backward on the bath
progressNum = (progressNum - 1) % circuit.Waypoints.Length;
}
}
target.position = circuit.Waypoints[progressNum].position;
target.rotation = circuit.Waypoints[progressNum].rotation;
// get our current progress along the route
progressPoint = circuit.GetRoutePoint(progressDistance);
Vector3 progressDelta = progressPoint.position - transform.position;
if (Vector3.Dot(progressDelta, progressPoint.direction) < 0)
{
progressDistance += progressDelta.magnitude;
}
lastPosition = transform.position;
}
}
private void OnDrawGizmos()
{
if (Application.isPlaying)
{
Gizmos.color = Color.green;
Gizmos.DrawLine(transform.position, target.position);
Gizmos.DrawWireSphere(circuit.GetRoutePosition(progressDistance), 1);
Gizmos.color = Color.yellow;
Gizmos.DrawLine(target.position, target.position + target.forward);
}
}
}
}
What i want is lets say i have a waypointSystem a straight line. I want both the sphere roll from point Start to point Finish, both will roll the same way. But what i mean with the sphere not going right or left is when they both follow the waypointSystem they follow it exactly the same route.
So i want them to drive a litle of the waypoint randomly so they are both going the same way following the waypoint but they arnt in the exact same path. So the rolling to the finnish gets a litle random per sphere.
yah that’s what i thought you where after. go back to my third post. you want to add some randomness to the waypoint target.
What did you get when you used my code (the third response.)?
you didn’t specify if the game was 2D or 3D so I assumed 3D.
if SetTarget() is getting called a lot then you might get a jittery movement.
second when i replaced my public void SetTarget with this code:
public void SetTarget(Transform WaypointTargetObject)
{
m_Target = WaypointTargetObject;
//add in a random verable to make the NPC not go directly to the waypoint
float X = Random.Range(-10.0f, 10.0f);
float Y = Random.Range(-10.0f, 10.0f);
float Z = Random.Range(-10.0f, 10.0f);
m_Target.position = m_Target.position + new Vector3(X, Y, Z);
}
I didnt get any error but the sphere is still acting like it did earlier without the code, it follows the exact same path.
I use 2 sphere that follow eaach other and the back is following the one in front exactly the same way, its no randomness. And what i would like is like if it can change position like every 10 sec to prevent jittering movement.
Also tried carl code change the last line of your code with his line but no effect.
Edit: So my guess is if i can get the target object that my sphere is following to randomly follow the waypoint a litle to the left or right, then it would solve my issue but i dont now how.
Can you tell me in to code where the NPC moves? IE: transform.position = someplace; or it could be rigidbody.velocity
Where ever that peace it at. then just add in some random values.
in RollerBallNpc I see you are using m_Rigidbody.velocity
you can try
m_Rigidbody.velocity = new Vector3(normalizedDirection.x * m_MaxAngularVelocity + Random.Range(-10.0f, 10.0f), -5, normalizedDirection.z * m_MaxAngularVelocity + Random.Range(-10.0f, 10.0f));
Yeah thats the code that make it moves but still no work, what i think is i need the gameobject i have as a child of my sphere that i attatch to m_Target, is the one that need to move a litle left or right cause the sphere follows that gameobject and wont move away from it, so im guessing i need the gameobject that are attach as a child of my sphere to be the one moving random. if you cant figure it out its ok, but thanks alot for trying:)
Thank johne5 and carl010010 with your suggestions i think i did it and sorry for late reply havnt solved this before now…
I use torque now instead of the velocity and added and changed some of the code you guys wrote, the random.range seem to work now, i will post the script here if anyone need it and i have 1 question about it if anyone can explain something, and again thanks alot for the help.
using UnityEngine;
using System.Collections;
public class RollerBallNpc : MonoBehaviour
{
private Rigidbody m_Rigidbody;
[SerializeField] private Transform m_Target;
[SerializeField] private float m_Power = 5;
[SerializeField] private float m_MaxAngularVelocity = 15;
[SerializeField] private float ChangeRandomInSeconds = 5;
[SerializeField] private float RandomXMin = -4;
[SerializeField] private float RandomXMax = 4;
[SerializeField] private float RandomX; //No point in changing this, only have it so you can see the value in the inspector
[SerializeField] private float RandomZMin = -4;
[SerializeField] private float RandomZMax = 4;
[SerializeField] private float RandomZ; //No point in changing this, only have it so you can see the value in the inspector
// Use this for initialization
void Start()
{
StartCoroutine("DoCheck");
RandomX = Random.Range(RandomXMin, RandomXMax);
RandomZ = Random.Range(RandomZMin, RandomZMax);
m_Rigidbody = GetComponent<Rigidbody>();
GetComponent<Rigidbody>().maxAngularVelocity = m_MaxAngularVelocity;
}
void FixedUpdate()
{
m_Target.position = new Vector3(m_Target.position.x + RandomX, m_Target.position.y, m_Target.position.z + RandomZ);
Vector3 normalizedDirection = (m_Target.transform.position - m_Rigidbody.transform.position).normalized;
m_Rigidbody.AddTorque(new Vector3(normalizedDirection.z, 0, -normalizedDirection.x) * m_Power);
}
public void SetTarget(Transform WaypointTargetObject)
{
m_Target = WaypointTargetObject;
}
IEnumerator DoCheck()
{
for (;;)
{
RandomX = Random.Range(RandomXMin, RandomXMax);
RandomZ = Random.Range(RandomZMin, RandomZMax);
yield return new WaitForSeconds(ChangeRandomInSeconds);
}
}
}
The x and z are at the wrong places and i tried switch them and used all combinations on the 2 of minus and no minus. And if i change the 2 no matter where i put or dont put the minus it wont work, but as it is now it does so can anyone explain why that is?