showing issue of projectiles not traveling to cursor when rotating player camera.
the camera is parented to player
how do i fix the issue? what should i look at?
The script on my player object.
using Lean.Pool;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using static UnityEngine.GraphicsBuffer;
public class Player : MonoBehaviour
{
#region Variables
//Player movement variables
public float speed;
private float movementX;
private float movementY;
private CharacterController characterController;
//Player camera rotation variables
public float rotateSpeed;
private float rotateX;
//Player camera snap variables
public float snapAngle = 90f;
//Player camera offcentre toggle variables
bool offCentre;
public Transform cameraPosition1;
public Transform cameraPosition2;
public Transform playerCamera;
//player shooting variables
public GameObject bulletPrefab;
public Transform spawnPoint;
public float rateOfFire; // Bullets per second
private float nextFireTime = 0f;
private float shootInput;
//player aiming variables
public Camera mainCamera;
[SerializeField] private LayerMask groundMask;
public Vector3 playerAimAt;
#endregion
private void Awake()
{
characterController = GetComponent<CharacterController>();
}
private void Start()
{
}
void Update()
{
MouseAim();
MovePlayer(); //since character controller is being used, no rigid body is being used, no need for fixedupdate.
SpawnBullet();
}
private void LateUpdate()
{
RotatePlayer(); //camera related stuff, do after moving player, smooth camera as result maybe
}
#region Move player
private void OnMove(InputValue movementValue)
{
Vector2 movementVector = movementValue.Get<Vector2>();
movementX = movementVector.x;
movementY = movementVector.y;
}
private void MovePlayer()
{
Vector3 forward = Camera.main.transform.forward; //calculate the viewing angle between player and camera
Vector3 right = Camera.main.transform.right; //calculate the viewing angle between player and camera
forward.y = 0.0f; //potentially unnecessary, however worth overengineering for.
right.y = 0.0f; //potentially unnecessary, however worth overengineering for.
forward = forward.normalized; //constrict magnitude to 1
right = right.normalized; //constrict magnitude to 1
Vector3 forwardRelative = movementY * forward;
Vector3 rightRelative = movementX * right;
Vector3 cameraRelative = forwardRelative + rightRelative;
characterController.Move(speed * Time.deltaTime * cameraRelative);
}
#endregion
#region Rotate camera
private void OnRotate(InputValue rotateValue)
{
float rotateVector = rotateValue.Get<float>(); //1d axis float between -1 and 1 bound by dpad L/R and Q/E respectively
rotateX = rotateVector; //converting private var to var use in RotatePlayer()
}
private void RotatePlayer()
{
Vector3 rotate = new(0.0f, rotateX, 0.0f); //twist top axis of player rather than other axis'
transform.Rotate(rotateSpeed * Time.deltaTime * rotate); //multiply by time and serialized rotation speed
}
#endregion
#region Camera snap
private void OnSnap(InputValue snapValue)
{
float x = snapValue.Get<float>(); //button press defaults 0 on idle, when pressed stays to 1
if (x == 1) //when button pressed
{
Vector3 currentRotation = transform.eulerAngles; //get current transform rotation
float snappedYRotation = Mathf.Round(currentRotation.y / snapAngle) * snapAngle; //Calculate the nearest 90
transform.eulerAngles = new Vector3(currentRotation.x, snappedYRotation, currentRotation.z); // Set the new rotation
x = 0; //tell button its off again. bootleg GetKeyDown... works fine
}
}
#endregion
#region Camera toggle centre
private void OnCentre(InputValue centreValue)
{
float x = centreValue.Get<float>(); //button press defaults 0 on idle, when pressed stays to 1
if (offCentre && x == 1) //when button pressed
{
mainCamera.transform.position = cameraPosition2.position;
x = 0;
offCentre = false;
}
else if (!offCentre && x == 1)
{
mainCamera.transform.position = cameraPosition1.position;
x = 0;
offCentre = true;
}
}
#endregion
#region player shoot
private void OnShoot(InputValue shootValue)
{
float x = shootValue.Get<float>();
shootInput = x;
}
private void SpawnBullet()
{
if (shootInput == 1 && Time.time >= nextFireTime)
{
Instantiate(bulletPrefab, spawnPoint.position, spawnPoint.rotation);
nextFireTime = Time.time + 1f / rateOfFire;
Debug.Log("position: " + playerAimAt);
}
}
private void MouseAim()
{
var (success, position) = GetMousePosition();
if (success)
{
// Ignore the height difference.
position.y = 0;
// Make the transform look in the direction.
playerAimAt = position.normalized;
}
}
private (bool success, Vector3 position) GetMousePosition()
{
var ray = mainCamera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out var hitInfo, Mathf.Infinity, groundMask))
{
// The Raycast hit something, return with the position.
return (success: true, position: hitInfo.point);
}
else
{
// The Raycast did not hit anything.
return (success: false, position: Vector3.zero);
}
}
#endregion
}
the script attached to the bullet prefab
using Unity.VisualScripting;
using UnityEngine;
public class StraightBullet : MonoBehaviour
{
public float damage; // the damage this projectile will inflict
public float projectileSpeed; // float speed of projectile
public float projectileLifetime; // float in seconds the projectile will be deleted after
private Vector3 target; // the vector the projectile moves towards
public bool penetrate; // Projectile penetrates enemies?
private Player playerScript; // Reference to the Player script
private void Start()
{
Destroy(gameObject, projectileLifetime); // no matter what, destroy after such time.
playerScript = GameObject.FindObjectOfType<Player>(); // search for the player script
if (playerScript == null) //simple debug error check
{
Debug.LogError("Player script not found");
return;
}
target = playerScript.playerAimAt; // Vector3 target variable in player script from mouse input
Debug.Log("shot: "+target);
}
private void Update()
{
transform.Translate(projectileSpeed * Time.deltaTime * target);
}
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag("Wall"))
{
Destroy(gameObject);
}
if (other.gameObject.CompareTag("Enemy"))
{
var hp = other.GetComponent<Enemy>().health -= 1;
Debug.Log(hp);
if (!penetrate)
{
Destroy(gameObject);
}
}
}
}