- Home /
Why does the transform don’t move correct?
Hi there, I’m new to Unity and after working through the tanks tutorial I started to modify the tutorial game to get more practice with Unity. My first “small” task is to rotate the tank turret with the mouse. I got this working. Turret and FireTransform follow the mouse cursor. But when I turn the tank with the arrow or aswd keys the FireTransform follows the tank body. I made a small video to demonstrate the behaviour. The first fifteen seconds shows the turret turning with mouse, the rest the FireTransform behaviour when turning the tank with keys.
Here is the modified code
using UnityEngine;
public class TankMovement : MonoBehaviour
{
public int m_PlayerNumber = 1;
public float m_Speed = 12f;
public float m_TurnSpeed = 180f;
public AudioSource m_MovementAudio;
public AudioClip m_EngineIdling;
public AudioClip m_EngineDriving;
public float m_PitchRange = 0.2f;
private string m_MovementAxisName;
private string m_TurnAxisName;
private Rigidbody m_Rigidbody;
private float m_MovementInputValue;
private float m_TurnInputValue;
private float m_OriginalPitch;
private Transform m_TurretTransform;
private Transform m_FireTransform;
private Transform m_ChassisTransform;
private void Awake()
{
m_Rigidbody = GetComponent<Rigidbody>();
FindTurretAndFireTransform();
}
private void FindTurretAndFireTransform()
{
Transform[] transforms = GetComponentsInChildren<Transform>();
foreach (Transform transform in transforms)
{
if (transform.tag == "Turret")
m_TurretTransform = transform;
if (transform.tag == "FireTransform")
m_FireTransform = transform;
if (transform.tag == "Chassis")
m_ChassisTransform = transform;
}
}
private void OnEnable()
{
m_Rigidbody.isKinematic = false;
m_MovementInputValue = 0f;
m_TurnInputValue = 0f;
}
private void OnDisable()
{
m_Rigidbody.isKinematic = true;
}
private void Start()
{
m_MovementAxisName = "Vertical" + m_PlayerNumber;
m_TurnAxisName = "Horizontal" + m_PlayerNumber;
m_OriginalPitch = m_MovementAudio.pitch;
}
private void Update()
{
// Store the player's input and make sure the audio for the engine is playing.
m_MovementInputValue = Input.GetAxis(m_MovementAxisName);
m_TurnInputValue = Input.GetAxis(m_TurnAxisName);
EngineAudio();
}
private void EngineAudio()
{
// Play the correct audio clip based on whether or not the tank is moving and what audio is currently playing.
if (Mathf.Abs(m_MovementInputValue) < 0.1f && Mathf.Abs(m_TurnInputValue) < 0.1f)
{
if (m_MovementAudio.clip == m_EngineDriving)
{
m_MovementAudio.clip = m_EngineIdling;
m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);
m_MovementAudio.Play();
}
}
else
{
if (m_MovementAudio.clip == m_EngineIdling)
{
m_MovementAudio.clip = m_EngineDriving;
m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);
m_MovementAudio.Play();
}
}
}
private void FixedUpdate()
{
// Move and turn the tank.
Move();
Turn();
TurnTurret();
}
private void Move()
{
// Adjust the position of the tank based on the player's input.
Vector3 movement = transform.forward * m_MovementInputValue * m_Speed * Time.deltaTime;
m_Rigidbody.MovePosition(m_Rigidbody.position + movement);
}
private void Turn()
{
// Adjust the rotation of the tank based on the player's input.
float turn = m_TurnInputValue * m_TurnSpeed * Time.deltaTime;
Quaternion turnRotation = Quaternion.Euler(0f, turn, 0f);
m_Rigidbody.MoveRotation(m_Rigidbody.rotation * turnRotation);
}
private void TurnTurret()
{
//adjust the turret rotation based on the mouse position
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
if (hit.collider != null)
{
//adjust turret
m_TurretTransform.LookAt(new Vector3(hit.point.x, m_TurretTransform.position.y, hit.point.z));
//adjust fire transform
Vector3 firePosition = m_TurretTransform.forward * 1.35f + m_TurretTransform.up * 1.7f;
m_FireTransform.localPosition = firePosition;
m_FireTransform.rotation = m_TurretTransform.rotation;
m_FireTransform.Rotate(350, 0, 0);
}
}
}
Answer by admiral_apfel · Jul 06, 2017 at 08:07 PM
Thanks all for your input. Changing the parent/child hierarchy and determine the firePosition shown in the following code solves the problem.
FireTransform correct behavior
private void TurnTurret()
{
//adjust the turret rotation based on the mouse position
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
if (hit.collider != null)
{
//adjust turret
m_TurretTransform.LookAt(new Vector3(hit.point.x, m_TurretTransform.position.y, hit.point.z));
//adjust fire transform
Vector3 firePosition = new Vector3(0, m_TurretTransform.localPosition.y - 0.5f, m_TurretTransform.localPosition.z + 1.35f);
m_FireTransform.localPosition = firePosition;
m_FireTransform.rotation = m_TurretTransform.rotation;
m_FireTransform.Rotate(350, 0, 0);
}
}
Answer by Cornelis-de-Jager · Jul 06, 2017 at 02:53 AM
Your script IS working. You are turning, just very very slowly.
private void Turn()
{
// Adjust the rotation of the tank based on the player's input.
float turn = m_TurnInputValue * m_TurnSpeed * Time.deltaTime;
...
}
Change the above function to:
// Adjust the rotation of the tank based on the player's input.
float turn = m_TurnInputValue * m_TurnSpeed;
So remove the Time.deltaTime. It is only necessary when moving rather than rotating.
ehhh I dont think so. time.deltaTime definitely applies to rotation.
You are possibly correct. But Time.deltaTime is about 0.001f in float value. $$anonymous$$eaning 0.001f * 180 = 0.180 degrees a second. Even if it was 0.01f degrees it will still be 1.8f degrees every second. Which is pretty slow concidering there are 360 degrees. $$anonymous$$eaning it will take more than 5 $$anonymous$$utes to make a full revolution.
$$anonymous$$ultiplied again by the m_TurnInputValue. You can see it turning. It's fine. But for another reason the numbers could be changed and deltaTime removed.
That's because you are already in FixedUpdate() which runs at fixed intervals.
You aren't seeing anything turn slowly. It's all turning just right. The problem is that firePosition is not suited for a localPosition in this case. firePosition is a vector relatively small in magnitude. keeping the fire transform close to the tank, but it's not the point at the end of the turret if used as a localPosition.
Answer by Jwizard93 · Jul 06, 2017 at 03:40 AM
The FireTransform has an offset from it's parent transfer. When the parent rotates the child transform moves in a circle with the radius of it's offset.
firePosition is based on WorldCoordinates but you are using it to set the FireTransforms local position, i.e. its location relative to the parent.
set FireTransform.position = firePosition instead.
In addition the fireTransform should be a child of the turret ins$$anonymous$$d of the actual tank. Currently the turret and the firetransform seem to be both direct childs of the tank.
Why should the FireTransform be a Child of the turret?
Because, assu$$anonymous$$g the turret rotates, if it is a child of the tank, it is going to give some fairly unorthodox behavior. All objects should be childed to the their respective parents to the extent of what makes sense to the task. Like in a car, you wouldn't child the wheels to the body, you would child the wheels to the axle.
Your answer
![](https://koobas.hobune.stream/wayback/20220612125523im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
How do I modify the current transform? 2 Answers
spawn forward 1 Answer
How to make a object translate alonge an other 2 Answers
Not able to change GameObject transform axis !! 1 Answer
Rotating Y towards X/Z 1 Answer