- Home /
How to rotate a tank turret and gun?
Hi all. I am trying to build a first person tank game. As you can see in the attached video, I have used a smooth look at action to get the turret and gun to follow where I point my mouse, however, I cannot figure out how to constrain the gun to the vertical axis. Right now it just follows anywhere. I just want the gun to move up and down to where I point the camera. Help?
Answer by bpaynom · Jul 09, 2019 at 06:46 PM
In the LateUpdate()
callback, set the localRotation of the gun like this.
public class ClampRotation : MonoBehaviour
{
public GameObject gun;
void LateUpdate()
{
// if you want to clamp on X-Axis
gun.transform.localEulerAngles = new Vector3( gun.transform.localEulerAngles.x, 0, 0 );
}
}
EDIT: If you want to clamp the the degrees then you can add two extra fields
[SerializeField] private float minAngle, maxAngle;
public class ClampRotation : MonoBehaviour
{
public GameObject gun;
void LateUpdate()
{
float clampedAngle = Mathf.Clamp( gun.transform.localEulerAngles.x, minAngle, maxAngle );
// if you want to clamp on X-Axis
gun.transform.localEulerAngles = new Vector3( clampedAngle , 0, 0 );
}
}
Answer by DOLJMAA_GAMES · Jul 10, 2019 at 03:25 AM
@ConcanoPayno thanks, but I've run into a problem. I keep getting this error that the name "gun" does not exist in the current context. Here is the source code for the gun
using UnityEngine;
namespace HutongGames.PlayMaker.Actions
{
[ActionCategory(ActionCategory.Transform)]
[Tooltip("Smoothly Rotates a Game Object so its forward vector points at a Target. The target can be defined as a Game Object or a world Position. If you specify both, then the position will be used as a local offset from the object's position.")]
public class SmoothLookAt : FsmStateAction
{
[RequiredField]
[Tooltip("The GameObject to rotate to face a target.")]
public FsmOwnerDefault gameObject;
[Tooltip("A target GameObject.")]
public FsmGameObject targetObject;
[Tooltip("A target position. If a Target Object is defined, this is used as a local offset.")]
public FsmVector3 targetPosition;
[Tooltip("Used to keep the game object generally upright. If left undefined the world y axis is used.")]
public FsmVector3 upVector;
[Tooltip("Force the game object to remain vertical. Useful for characters.")]
public FsmBool keepVertical;
[HasFloatSlider(0.5f,15)]
[Tooltip("How fast the look at moves.")]
public FsmFloat speed;
[Tooltip("Draw a line in the Scene View to the look at position.")]
public FsmBool debug;
[Tooltip("If the angle to the target is less than this, send the Finish Event below. Measured in degrees.")]
public FsmFloat finishTolerance;
[Tooltip("Event to send if the angle to target is less than the Finish Tolerance.")]
public FsmEvent finishEvent;
private GameObject previousGo; // track game object so we can re-initialize when it changes.
private Quaternion lastRotation;
private Quaternion desiredRotation;
public override void Reset()
{
gameObject = null;
targetObject = null;
targetPosition = new FsmVector3 { UseVariable = true};
upVector = new FsmVector3 { UseVariable = true};
keepVertical = true;
debug = false;
speed = 5;
finishTolerance = 1;
finishEvent = null;
}
public override void OnPreprocess()
{
Fsm.HandleLateUpdate = true;
}
public override void OnEnter()
{
previousGo = null;
}
void LateUpdate()
{
//clamp on X-Axis
gun.transform.localEulerAngles = new Vector3(gun.transform.localEulerAngles.x, 0, 0);
}
public override void OnLateUpdate()
{
DoSmoothLookAt();
}
void DoSmoothLookAt()
{
var go = Fsm.GetOwnerDefaultTarget(gameObject);
if (go == null)
{
return;
}
var goTarget = targetObject.Value;
if (goTarget == null && targetPosition.IsNone)
{
return;
}
// re-initialize if game object has changed
if (previousGo != go)
{
lastRotation = go.transform.rotation;
desiredRotation = lastRotation;
previousGo = go;
}
// desired look at position
Vector3 lookAtPos;
if (goTarget != null)
{
lookAtPos = !targetPosition.IsNone ?
goTarget.transform.TransformPoint(targetPosition.Value) :
goTarget.transform.position;
}
else
{
lookAtPos = targetPosition.Value;
}
if (keepVertical.Value)
{
lookAtPos.y = go.transform.position.y;
}
// smooth look at
var diff = lookAtPos - go.transform.position;
if (diff != Vector3.zero && diff.sqrMagnitude > 0)
{
desiredRotation = Quaternion.LookRotation(diff, upVector.IsNone ? Vector3.up : upVector.Value);
}
lastRotation = Quaternion.Slerp(lastRotation, desiredRotation, speed.Value * Time.deltaTime);
go.transform.rotation = lastRotation;
// debug line to target
if (debug.Value)
{
Debug.DrawLine(go.transform.position, lookAtPos, Color.grey);
}
// send finish event?
if (finishEvent != null)
{
var targetDir = lookAtPos - go.transform.position;
var angle = Vector3.Angle(targetDir, go.transform.forward);
if (Mathf.Abs(angle) <= finishTolerance.Value)
{
Fsm.Event(finishEvent);
}
}
}
}
}
I apologize, but I am very new to scripting. I have been using Unity Playmaker lately and only in the past week have I started working on hand scripting. What am I doing wrong here? thanks for your time.
I keep getting this error that the name "gun" does not exist in the current context.
You have to define that variable ( like I did on line 3 of my code), and asign the gun in the inspector.
Awesome! It worked! thank you so much. One last question, how do I limit it's gun arc? I want the gun to be able to aim only 15 degrees up and 8 degrees down. How do I do that? Thanks again!
Your answer
Follow this Question
Related Questions
Flip over an object (smooth transition) 3 Answers
Making a bubble level (not a game but work tool) 1 Answer
Why the player is not rotating and moving at the same time ? 0 Answers
Saving Rotation of Sprite 1 Answer
Trigonometric functions 2 Answers