I've got entities that need to wander around the world, and I want to model random but also semi-directed behavior. What I'd prefer is a behavior that picks a random forward vector within a range of forward vectors relative to the entity's current forward direction. What is a good way to pull this off? I've tried rotating the entities forward vector in pos/neg directions and lerping between them randomly to find the new forward direction, but I'm not getting it to work, and I don't know enough about Unity's vectors to figure out the correct approach.
#Choosing a random wander direction
1 messages · Page 1 of 1 (latest)
`public override Vector3 GetDestination(Ant ant)
{
// should calculate travel radius based on ant speed and choose a random point within that radius
Vector3 up = ant.transform.up;
Vector3 leftVector = Quaternion.AngleAxis(100, up) * up;
Vector3 rightVector = Quaternion.AngleAxis(-100, up) * up;
Vector3 guessDirection = Vector3.Lerp(leftVector, rightVector, Random.Range(0f, 1f));
// in the meantime:
Vector3 destination = ant.transform.position + guessDirection * 1;
Debug.Log("Ant" + ant.id + ": " + guessDirection + ", " + ant.transform.position + ", " + destination);
return destination;
}
`
ant.transform.up is the ant's actual forward direction, since I'm currently just using a Capsule object on its side.
{
return antPosition + Quaternion.Euler(0, Random.Range(0, 360), 0) * Vector3.forward * distance;
}```
do u mean like
something like that?
ohhh ant.transform.up
u need it relative to the ants .up direction
Yes, but I could do Random.Range(-30, 30) to get a 60 degree arc from ant.transform.up?
yes
you would need to take the ants euler angle
like this
I am learning about quaternions and angles etc but it's a bit much to learn lol
Basically, the ant needs to choose a direction in this range in front of it: \/, where "front" is "up" lol
it is 3D
private Vector3 randomWanderTarget(float distance, Vector3 antPosition, Quaternion antRotation, float wanderRange)
{
Vector3 targetOffset = Quaternion.Euler(antRotation.eulerAngles + new Vector3(0, Random.Range(-wanderRange, wanderRange), 0)) * Vector3.forward * distance;
return antPosition + antRotation * targetOffset;
}
in 3D: var rot = Quaternion.AngleAxis(Random.Range(-30, 30), transform.up)
this will be a random rotation between -30 and 30 degrees around the ant's local up vector
you can then apply this rotation to a vector
rot * transform.forward
this will be a new vector rotated by up to 30 degrees
now how do I ensure the rotation is along the correct plane, though? because couldn't it just as well rotate the up vector up/down as well as left/right or anything at all, really?
That's why you use AngleAxis
it produces a rotation around an axis
If the ant spins around its up vector (which is usually what you're doing in 3D), then this will randomly rotate the ant horizontally
Is this even the best approach? Is angles/rotations costly? Compared to some sort of vector shortcut to produce the desired direction vector? I try to avoid linear algebra lol
it's fine.
the math is pretty simple (for your computer)
You could also just add a random vector to your forward vector and normalize it
This doesn't give you a precise angle range.
ohhhhhh, this makes sense. I do not want to rotate around the up axis of the ant. I want to rotate the up axis itself about the effective up axis
the ant is a capsule on it's side. so up is the direction it walks, and the effective up is either x or z depending on the capsule's rotation about the actual up axis (y)
Vector3 offset = 0.2f * Random.insideUnitSphere;
offset = Vector3.ProjectOnPlane(offset, transform.up);
transform.forward = transform.forward + offset;
this would perturb the forward vector by uh
a small amount
i'm not sure what angles that'd give you
the ProjectOnPlane throws out the part in the up direction
so that the resulting offset vector only works in the local X and Z directions
Just make the model a child of the actual Ant object
That way its rotation is irrelevant
do you mind saying more? what model?
the capsule.
you mean instead of having the capsule be a component of the ant object, have it be a child?
make the object with the mesh renderer a child of the actual Ant object
yes
it sounds very annoying to have to keep the thing rotated correctly so that the capsule stays on its side
And this means that I just set the child's orientation when I need and use the Ant's own forward/up to orient it when needed?
100% lol
set the child's orientation once
so that the capsule is on its side
then control the parent's orientation as it moves around
ok let me ask a little more then. i'm still learning. the Ant GameObject can have its own transform component to track it's movement and the Ant can also have a 3D model (composite or just a capsule) with it's own transform to determine its orientation?
but i do want the ant to face the direction it is traveling, so when updating the ants direction, i would also want to update the model's direction?
Every GameObject has a transform.
The capsule object is going to be a child of the Ant.
That means that its parent's transform gets applied to it as well, basically
Rotate the parent 90 degrees, rotate the child 90 degrees
ah i see
i think
If you put the child at [5,0,0] relative to its parent
and then spin the parent
the child will trace out a circle around its parent
ok so ant.transform.up would not equal ant.model.transform.up, but that's ok, because relatively it all works out
Right.
got it
transform.up is your local up vector
+Y in local space
in world space, it depends on your rotation
yes this is what is giving me trouble lol
i think i got it now
is there best practice for managing scale, etc? i mean, i've added an AntModel child (just a capsule for now) to the Ant object. Do I set the scale for the parent or the child? It seems like there must be a better strategy for tuning those values than just guessing and checking. lol
makes sense
if you want to change the propotions, then definitely change the child's size
non-uniform scaling causes problems for child objects
specifically when they rotate
they wind up getting skewed
it looks like my parent transform and my child transform diverge from each other on collision with another object. how do you fix the child transform to always be the parent transform?
easy to fix by making the child rigidbody kinematic, but i do want collisions to occur.
i can also fix it by adding a rigidbody component to the parent object (which i wasn't doing previously). but the behavior is so much more strange when there's a rigidbody on the parent as opposed to when there is only a kinematic rigidbody on the child. the ants seem to jump from destination to destination, as opposed to gliding there when there's no rigidbody
If you're using a rigidbody, you must tell the rigidbody to move
rather than just setting the transform directly
Rigidbody.MovePosition would be what you want
or just setting the velocity of the rigidbody
the child shouldn't have an RB
can i not access the rigidbody component of a particular object with this.rigidbody? why GetComponent?
Like why does ant.transform work?
Why don't you have to GetComponent<Transform>()?
Every GameObject is guaranteed to have a Transform
and every Component is guaranteed to be on a GameObject
so every Component can also be guaranteed to have a Transform
hence the property
you aren't guaranteed to have a Rigidbody.
Unity DID used to have some other properties for common components
light, renderer, etc.
but these are long gone
ok but presumably the parent object also needs a mesh as well?
No, since it’s not responsible for the visuals