Quaternion.Slerp not working as I think it should...

here is my code, what I want it to do is rotate the object so the +Z is pointing towards the floor to create a parabolic shape of a projectile traveling. What I get is it seems to want to avoid certain directions and turns away from them… I simply want the projectile to rotate towards the floor as it travels.

transform.localRotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(((transform.position + Vector3.down) - transform.position), transform.position), Time.deltaTime * drop);

1635582--101119--$Illustration.png

And this is an example of what is occuring when I fire instead of it traveling straight and then dropping.
It is a picture from above looking down at my ‘character’ firing. when facing 0,0,0 (which it is in this picture) the bullets split off and curve in a strange way to reach what is under it.

1635582--101120--$illustration 2.png

Here is the rest of the code if it helps, I wish there was an easy button here. I just want the front end to tip downward in the direction its traveling which is always forward on the Z axis…

float Distance = speed*Time.deltaTime;
		if(speed > stopspeed)
		{
			if(LockOn == true)
			{
				transform.rotation = Quaternion.Slerp(transform.rotation, (Quaternion.LookRotation(Target.transform.position - transform.position)), Time.deltaTime * 2);
			}
			else
			{
				
				transform.localRotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(((transform.position + Vector3.down) - transform.position), transform.position), Time.deltaTime * drop);
			}

		if (Physics.Raycast(transform.position, transform.forward, out hit, Distance, ~(1<<9) ))
		{
			if(Bounce == true)
			{
				Vector3 v3NewDirection = Vector3.Reflect ((hit.point - transform.position).normalized , hit.normal);
				Quaternion newrote = Quaternion.LookRotation(v3NewDirection, Vector3.up);
				transform.localRotation = newrote;
					speed *= drag;
			}
			else
			{
					if(radius > 0)
					{
						Instantiate(explosion, transform.position, transform.rotation);
					}
				Destroy (gameObject);
			}
					//Debug.Log("Hit Something");
		}
		
		
			transform.localPosition += transform.forward * Distance;
}

First of all, [co de] code tags [/code]!

Second: It looks like you’re using the wrong control variable for the last parameter of Slerp. Just like Anything.Lerp, this is a common newbie misunderstanding.

When you use Lerp/Slerp, the final parameter is a number between 0 and 1. If it’s 0, it returns your first value. If it’s 1, it returns the second. Anything in between, it returns a smoothly interpolated value between the two.

So instead of sending it “Time.deltaTime * 2” - which is basically going to always give you a rotation that is very close to the first parameter, but “jitters” slightly towards the second parameter depending on the framerate - you’ll want to keep track of a “float” variable, add Time.deltaTime * 2 to THAT variable, and send Slerp that variable instead.

It doesn’t really help that what the poster does here is in fact straight out of the Unity documentation, even though it is actually pretty much a trick usage of lerp, albeit quite common.

This code, and all other lerps of this style, asymptotically tend towards a value, resulting into a smooth move, slowing down while approaching the target. I simplified the code to just the slerp bit and does seem to manage to do that quite well.

It boils down to:

			Vector3 direction = Target.transform.position - transform.position;
			Quaternion target = Quaternion.LookRotation(direction);
			transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * RotationSpeed);

It will not “slightly jitter to the second parameter depending on the framerate”, because the first parameter is the current position, which is altered on every frame.

So, even though there are better ways to achieve this (see: problems if the framerate drops too much and the actual asymptotic behaviour itself), I do not think it’s the slerp that causes the poster’s issues.

I think how I instantiate the object is likely important as well… maybe its locking up for some reason??

for(int shotsfired = 0; shotsfired < bulletspershot+1; shotsfired++)
			{
				xrotation = (Random.Range(-50+accuracy,50 - accuracy));
				yrotation = (Random.Range(-50+accuracy,50 - accuracy));
				mygun.transform.localEulerAngles = new Vector3(mycamera.transform.localRotation.x + xrotation,mycamera.transform.localRotation.y + yrotation,mycamera.transform.localRotation.z);
				//mygun.transform.localRotation = new Quaternion(mycamera.transform.localRotation.x + xrotation,mycamera.transform.localRotation.y + yrotation,mycamera.transform.localRotation.z, mycamera.localRotation.w);
				Instantiate(bullet,mygun.position,mygun.rotation);

assuming this is the issue, is there a way I can instantiate the object in a non gimbal locked state facing the direction I need it to travel?

So it seems to want to avoid 0,0,0 world space for some reason… is there some way to keep it from doing this?

I really need this. I can’t proceed without it…

pointing towards the floor
or
pointing towards the movement parabolic curve shape that ends pointing towards the floor?
In this case you just need a look at target “last past position” and then flip *-1 the rotation to point where you are going. :wink:

Can you make a drawing of what you need?:face_with_spiral_eyes:

did so links at the top

All of my projectiles travel along their local positive Z axis. I tried to slerp the rotation to look towards global down, but at some angles it causes strange results. (the bullets turning away instead of simply looking down) I need the bullets to look down untill they reach a certain point. (close but not exactly global down) then stop rotating towards the ground. if they are no longer in that threshold they then need to begin rotating towards the floor again.

(as for why, it is because I have a game that uses thousands of bullets at a time and faking the physics without rigid bodies in this way allows me to have that many in the game at one time. This worked fine until I attempted to add in bullet drop by use of rotation. This does not seem like it should be that hard, but it is turning out to be a pain in the butt)

Sorry i do not understand the drawing and I do not like projectile bullets.

Is just a parabolic rotation?
Look image:

like this drawing?

Solution step by step.

First make an arrow that point a target.

using UnityEngine;
using System.Collections;

public class PointToTarget : MonoBehaviour 
{

	public GameObject dragTarget; // Drag here your Game Object target
        private Vector3 myVector;


	void Start () {

		if (dragTarget == null)
			Debug.LogError ("ATTENCION: This script ·PointToTarget· needs a GameObject targrt" + "\n");
	}
	

	
	void Update () {
		transform.LookAt(dragTarget.transform);
	}
}

You need a game Object as target.

if the arrow is not pointing correctly (modeling problems), you can add a correction.

using UnityEngine;
using System.Collections;

public class PointToTarget : MonoBehaviour {

	public GameObject dragTarget; // Drag here your Game Object target

        // Trim Rotation helper just in case
	public float arrowAngleX, arrowAngleY, arrowAngleZ;
	
        private Vector3 myVector;

	// Use this for initialization
	void Start () {
                // Just in case the arrow needs help rotation at start
		arrowAngleX = 90f; 
                arrowAngleY = 0f; 
                arrowAngleZ = 0f;

		if (dragTarget == null)
			Debug.LogError ("ATTENCION: This script ·PointToTarget· needs a GameObject targrt" + "\n");
	}
	
	// Update is called once per frame
	void Update () {
		transform.LookAt(dragTarget.transform);
		transform.Rotate (arrowAngleX, arrowAngleY, arrowAngleZ);
	}
}

Now Imagine an arrow in space that points to the past
You can yous this to make the rotation.

What you need is your past position (target) and your actual position.
So the arrow will point to the past.
If you flip it (-1), it will point to an approximation future.

using UnityEngine;
using System.Collections;

public class MovDirection : MonoBehaviour {

	private Vector3 lastPosition;
	private Vector3 actualPosition;
	


	void Start () {
		lastPosition = transform.position;
	}



	void FixedUpdate() {
		lastPosition = actualPosition;  // Here you get the target (the past position)
		actualPosition = transform.position;

		transform.LookAt(lastPosition);
		transform.Rotate (90f, 0f, 0f);
	}
}

I did not test it and I’m new coding.

At line 22

transform.Rotate (90f, 0f, 0f);

you can add 180° for example and your GameObject Arrow will point to the future approximation and not to the past.

Ps: If is what you need. If is not what you need, I can´t help you. I has to go! bb

I can’t seem to get it to work correctly, I also don’t think this would stop the rotation at true down.