Skip to main content

Raycasting with Changing Camera Angles

If in your creative you are using raycasts with the Camera.ScreenPointToRay method, you will find that if you change the camera position/angle in your replays using configured game variables that the input no longer functions properly. This is because the replay is using the new camera position to calculate those screen inputs.

To get around this you can use Replay's DataPrefs.Fetch API to store the world space coordinates of the raycast's hit location(s) during capture, and then load these values during replay. This will allow you to alter the camera angle during a replay without affecting the result of the raycasts.

If you are raycasting from the camera's position you may still encounter issues if you want the raycast to originate from the old camera position. To remedy this you can store the camera's position during capture as well and use it as the origin for the raycast.

Code Example#

public GameObject projectile;
public float speed = 50;
RaycastHit hit;
Vector3 camPos;
Quaternion camAngle;
private void Start() {
// Store the camera's position
camPos = DataPrefs.Fetch("camPos", () => GetComponent<Camera>().transform.position);
// Store the camera's rotation
camAngle = DataPrefs.Fetch("camAngle", () => GetComponent<Camera>().transform.rotation);
}
private void Update() {
if (!Input.GetMouseButtonUp(0)) {
return;
}
var ray = GetComponent<Camera>().ScreenPointToRay(Input.mousePosition);
// Store the ray's origin
var origin = DataPrefs.Fetch($"origin{Time.frameCount}", () => ray.origin);
// Store the ray's direction
var direction = DataPrefs.Fetch($"direction{Time.frameCount}", () => ray.direction);
// Raycast using the stored ray values
var cast = new Ray(origin, direction);
if (!Physics.Raycast(cast, out hit, Mathf.Infinity)) {
return;
}
// Instantiate projectile at the stored camera position & angle
var newProjectile = Instantiate(projectile, camPos, camAngle);
// Use the hit position and the stored camera position for velocity
newProjectile.GetComponent<Rigidbody>().velocity = (hit.point - camPos).normalized * speed;
}

Example in Replay#

images-large