The goal in the end is to rotate the object when he start moving so the object will facing towards the target he is moving to and also that the laser that coming out from the object eye will be facing the same target.
The object that i want to rotate is at first at position 0,0,0 because the object is a child. the player is holding the object by hand. Then the object is getting throw with animation towards a target.
The object is moving to the target but now i want the object to rotate also smooth slowly to the target in this case i set the rotation duration 1 second. and i see that the object rotation is changing but not facing the target.
This screenshot show the object while it's still in the player hand at position 0,0,0
Then the object get throw and start moving to the target at this time the object rotation change :
The object that throw have a child transform the eye and from the eye a laser beam should be coming out and then i want to make that the object will rotate towards the target so the laser from the eye will be facing the target.
I marked the eye with a small red circle :
In this screenshot i marked the target far away, the laser in green is not facing the target and also the eye is not facing the target. the laser should come out the eye and the whole object should facing the target so the laser also should be facing the target with the eye.
This screenshot is of the object before running the game the eye is facing forwards with the object. this is just to show that the eye is aligned with the object facing forward.
This script is attached to my player and make the object to be thrown to the target and also should make the object to be rotating towards the target :
The throw part that make the object move to the target is working fine but the rotating part is not :
private IEnumerator AnimateRotationTowards(Quaternion transformRot, Quaternion targetRot, float dur)
{
float t = 0f;
while (t < dur)
{
transformRot = Quaternion.Slerp(transformRot, targetRot, t / dur);
yield return null;
t = Time.deltaTime;
}
transformRot = targetRot;
}
Also i see that making transformRot = targetRot; for some reason there is a small message say unnecessary assignment not sure why.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ThrowObject : MonoBehaviour
{
public Transform objectToThrow;
public Transform target;
public Transform objectToThrowParent;
public float throwingSpeed;
public float waitAtTargetTime;
public float distanceToStopFromTarget;
public bool go = false;
public AnimationCurve animationCurve;
private Animator anim;
private bool startThrowAnimationOnce = true;
private bool reParent = false;
private bool startMovingBack = false;
private void Start()
{
anim = GetComponent<Animator>();
}
private void Update()
{
if (anim != null && startThrowAnimationOnce)
{
anim.SetTrigger("Throw");
startThrowAnimationOnce = false;
}
if (go)
{
objectToThrow.parent = null;
StartCoroutine(Throw());
StartCoroutine(AnimateRotationTowards(objectToThrow.rotation, target.rotation, 1f));
go = false;
}
if (reParent)
{
objectToThrow.position = objectToThrowParent.position;
}
if (startMovingBack)
{
if (Vector3.Distance(objectToThrow.position, objectToThrowParent.position) >= 0.1f)
{
float step = 5 * Time.deltaTime;
objectToThrow.position = Vector3.MoveTowards(objectToThrow.position, objectToThrowParent.position, step);
}
else
{
objectToThrow.position = objectToThrowParent.position;
objectToThrow.parent = objectToThrowParent;
objectToThrow.localPosition = new Vector3(0, 0, 0);
}
}
}
public void ThrowEvent()
{
go = true;
}
IEnumerator Throw()
{
while(Vector3.Distance(objectToThrow.position, target.position) >= distanceToStopFromTarget)
{
objectToThrow.position = Vector3.MoveTowards(
objectToThrow.position,
target.position,
throwingSpeed * Time.deltaTime
);
yield return null;
}
yield return new WaitForSeconds(waitAtTargetTime);
startMovingBack = true;
}
private IEnumerator AnimateRotationTowards(Quaternion transformRot, Quaternion targetRot, float dur)
{
float t = 0f;
while (t < dur)
{
transformRot = Quaternion.Slerp(transformRot, targetRot, t / dur);
yield return null;
t = Time.deltaTime;
}
transformRot = targetRot;
}
}
This script is attached to the object eye and fire the laser : The target in this script is the same target as in the ThrowObject script :
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters;
using System;
using UnityEngine;
public class Hovl_DemoLasers : MonoBehaviour
{
public List<Transform> targets;
public GameObject FirePoint;
public Camera Cam;
public float MaxLength;
public GameObject[] Prefabs;
private Ray RayMouse;
private Vector3 direction;
private Quaternion rotation;
[Header("GUI")]
private float windowDpi;
private int Prefab;
private GameObject Instance;
private Hovl_Laser LaserScript;
private Hovl_Laser2 LaserScript2;
private bool rotateMouse = true;
private bool startLaser = true;
private float buttonSaver = 0f;
private Hovl_LaserDemo hovl_laserDemo;
private float maxDistance = 0;
private int closestIndex = 0;
void Start()
{
if (Screen.dpi < 1) windowDpi = 1;
if (Screen.dpi < 200) windowDpi = 1;
else windowDpi = Screen.dpi / 200f;
Counter(0);
}
void Update()
{
//Enable lazer
if (Input.GetMouseButtonDown(0))
{
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
rotateMouse = true;
}
if (Input.GetMouseButtonDown(1))
{
rotateMouse = false;
}
if ((Input.GetKey(KeyCode.A) || Input.GetAxis("Horizontal") < 0) && buttonSaver >= 0.4f)// left button
{
buttonSaver = 0f;
Counter(-1);
}
if ((Input.GetKey(KeyCode.D) || Input.GetAxis("Horizontal") > 0) && buttonSaver >= 0.4f)// right button
{
buttonSaver = 0f;
Counter( 1);
}
buttonSaver = Time.deltaTime;
if (startLaser)
{
rotateMouse = false;
Destroy(Instance);
Instance = Instantiate(Prefabs[Prefab], FirePoint.transform.position, FirePoint.transform.rotation);
Instance.transform.parent = transform;
LaserScript = Instance.GetComponent<Hovl_Laser>();
LaserScript2 = Instance.GetComponent<Hovl_Laser2>();
hovl_laserDemo = Instance.GetComponent<Hovl_LaserDemo>();
startLaser = false;
}
if (targets != null)
{
maxDistance = Mathf.Infinity;
for (int i = 0; i < targets.Count; i )
{
float distance = Vector3.Distance(gameObject.transform.position, targets[i].position);
if (distance < maxDistance)
{
maxDistance = distance;
closestIndex = i;
}
}
if (hovl_laserDemo != null)
{
float distance = Vector3.Distance(gameObject.transform.position, targets[closestIndex].position);
MaxLength = distance;
hovl_laserDemo.MaxLength = distance;
}
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out hit, MaxLength))
{
RotateToMouseDirection(gameObject, targets[closestIndex].position);
}
else
{
RotateToMouseDirection(gameObject, targets[closestIndex].position);
}
}
if (Cam != null && rotateMouse)
{
RaycastHit hit;
var mousePos = Input.mousePosition;
RayMouse = Cam.ScreenPointToRay(mousePos);
if (Physics.Raycast(RayMouse.origin, RayMouse.direction, out hit, MaxLength))
{
RotateToMouseDirection(gameObject, hit.point);
}
else
{
var pos = RayMouse.GetPoint(MaxLength);
RotateToMouseDirection(gameObject, pos);
}
}
else
{
Debug.Log("No camera");
}
}
void OnGUI()
{
GUI.Label(new Rect(10 * windowDpi, 5 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use the keyboard buttons A/<- and D/-> to change lazers!");
GUI.Label(new Rect(10 * windowDpi, 20 * windowDpi, 400 * windowDpi, 20 * windowDpi), "Use left mouse button for shooting!");
}
void Counter(int count)
{
Prefab = count;
if (Prefab > Prefabs.Length - 1)
{
Prefab = 0;
}
else if (Prefab < 0)
{
Prefab = Prefabs.Length - 1;
}
}
void RotateToMouseDirection(GameObject obj, Vector3 destination)
{
direction = destination - obj.transform.position;
rotation = Quaternion.LookRotation(direction);
obj.transform.localRotation = Quaternion.Lerp(obj.transform.rotation, rotation, 1);
}
}
CodePudding user response:
This is one situation where it is important to understand the difference between passing by value, or passing by reference. In your AnimateRotationTowards
function, all of the parameters to that function are passed by value. Changes to those rotations will affect the local values within the function scope, but those are not the same values that get used in the scene.
What you probably want instead is a reference to some Transform
object. If you assign a new rotation to that Transform, it will use that rotation in the scene.
It looks like this script component is attached to the GameObject that will be rotating. Is that right? If yes, you can set a new rotation by assigning a value to transform.rotation
:
private IEnumerator AnimateRotationTowards(Quaternion transformRot, Quaternion targetRot, float dur)
{
float t = 0f;
while (t < dur)
{
transform.rotation = Quaternion.Slerp(transformRot, targetRot, t / dur);
yield return null;
t = Time.deltaTime;
}
transform.rotation = targetRot;
}
If you need to assign a rotation to some other GameObject, you can pass in a reference to that GameObject or its Transform and use that to assign the rotation.