- Home /
How can I fix the arm movement with the camera.
Trying to make a third person shooter and the goal right now is to get the arm (which a cylinder) to aim up and down. Right now, when the game starts, the cylinder position resets vertically but does aim with the camera but it offset really weird. Can someone please help me fix this? Im new to unity and am doing my best to learn
//Code for the arm
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class Arm : MonoBehaviour { public float mouseSensitivity = 100f;
public Transform arm;
float xRotation = 0f;
// Start is called before the first frame update
void Start()
{
//Cursor.lockState = CursorLockMode.Locked;
arm.transform.eulerAngles = new Vector3(arm.transform.eulerAngles.x, arm.transform.eulerAngles.y, arm.transform.eulerAngles.z);
}
// Update is called once per frame
void Update()
{
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
arm.Rotate(Vector3.up * mouseX);
}
}
//Code for the Camera
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class MouseLook : MonoBehaviour {
public float mouseSensitivity = 100f;
public Transform playerBody;
float xRotation = 0f;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
playerBody.Rotate(Vector3.up * mouseX);
}
}
// Code for the player movement
using System.Collections; using System.Collections.Generic; using UnityEngine;
public class PlayerMovement : MonoBehaviour {
CharacterController characterController;
public float speed = 3.0f;
public float jumpSpeed = 8.0f;
public float gravity = 20.0f;
public float shootSpeed = 20;
private Vector3 moveDirection = Vector3.zero;
public GameObject laserPrefab;
public GameObject firePoint;
// Start is called before the first frame update
void Start()
{
transform.position = new Vector3(-5, 1, -10);
characterController = GetComponent<CharacterController>();
}
// Update is called once per frame
void Update()
{
if (characterController.isGrounded)
{
// We are grounded, so recalculate
// move direction directly from axes
moveDirection = new Vector3(Input.GetAxis("Horizontal"), 0.0f, Input.GetAxis("Vertical"));
moveDirection *= speed;
if (Input.GetButton("Jump"))
{
moveDirection.y = jumpSpeed;
}
}
if (Input.GetMouseButtonDown(0))
{
Shoot();
}
// Player moves forward in direction of camera
Vector3 move = transform.right * moveDirection.x + transform.forward * moveDirection.z;
characterController.Move(move * speed * Time.deltaTime);
// Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
// when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
// as an acceleration (ms^-2)
moveDirection.y -= gravity * Time.deltaTime;
// Move the controller
characterController.Move(moveDirection * Time.deltaTime);
}
// Action to shoot
void Shoot()
{
GameObject laser = Instantiate(laserPrefab, firePoint.transform.position, firePoint.transform.rotation);
Rigidbody rb = laser.GetComponent<Rigidbody>();
rb.AddForce(transform.forward * shootSpeed, ForceMode.Impulse);
}
}
Answer by darksider2000 · May 13, 2020 at 06:32 PM
First off your code in Start() is redundant:
arm.transform.eulerAngles = new Vector3(arm.transform.eulerAngles.x, arm.transform.eulerAngles.y, arm.transform.eulerAngles.z);
So I skimmed through your post and what I think is causing your offset is the fact that you're using Transform.localRotation
If your cylinder has a parent (probably the character object/model) then localRotation will rotate it in local space relative to the parent. Instead of world space.
Give it a shot with Transform.rotation instead, and you shouldn't have any offset then.
void Update()
{
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f);
transform.rotation = Quaternion.Euler(xRotation, 0f, 0f);
arm.Rotate(Vector3.up * mouseX);
}
If this doesn't fix your issue try taking a screenshot of the offset if you can, that'd help single it out.
Gluck!
This issue is that when the game starts, the cylinder acting as the arm, resets to a up and down orientation when I start the game ins$$anonymous$$d of staying extended from the body. It will move with the camera but in order to fire straight, I have to aim the camera at the ground.
Ok sure I see what you mean.
This is how a regular cylinder in unity is created. The ends of the cylinder are on the Y axis, but you're ai$$anonymous$$g the Z axis at the target.
There's a quick and easy fix and that's just to add an extra 90 degrees of rotation to the X axis whenever you calculate the cylinder's rotation.
So:
transform.rotation = Quaternion.Euler(xRotation - 90, 0f, 0f); // -90 or +90 depending on if you want the transform.forward or -transform.forward pointing at the target
But if you're planning on adding graphical assets later on such as weapon models etc, I'd suggest you create an empty GameObject to handle the arm/weapon's code and put the mesh object (Cylinder in this case) as a child under the empty GameObject.
This will give you a lot of flexibility over the visual aspect without affecting the code behavior. For example: A rifle's recoil animation would move the gun model but not the parent, and so would not affect the alignment with camera view.