Set transform.position relative to rotation
Forgive my title, but I tried to make it somewhat generic to help other people who may fall in front of the same problem.
The problem:
I'm creating a pool sim where I can currently rotate the cue around the cue ball and want to be able to move the cue stick sideways between the edges of the cue ball. The issue I'm having is calculating the cue's position relative to the cue ball when the cue is rotated. I've managed to get the cue to move between the two edges of the cue ball, but once I rotate the cue around the cue ball (using the left and right keys) and then set the spin the cue is positioned incorrectly.
Note: The side spin is defined as a Vector2 where -1 (is all the way to the left, 0 is aligned to the centre of the cue ball and 1 is the right side of the cue ball).
private void Update()
{
float horizontal = Input.GetAxis("Horizontal");
transform.RotateAround(m_cueBallTrans.position, Vector3.up, horizontal * 50f * Time.deltaTime);
}
// x = 1.0 right side
// x = -1.0 left side
public void SetSpin(Vector2 spin)
{
// Calculate the max distance the cue can move in each direction
// (essentially half the cue ball either side)
float cueMaxSideDist = m_cueBallTrans.localScale.x * 0.5f;
// Get the amout we want to move to the edge of the cue ball
float cueSideAmount = cueMaxSideDist * Mathf.Clamp(spin.x, -1f, 1f);
// Get the right dir and multiple by cue side amount and then add 0.8 (magic number) in
// the backwards direction of the cue transform
transform.position = (transform.right.normalized * cueSideAmount) +
(-transform.forward.normalized * 0.8f);
}
I've added comments to the code to help with what I'm trying to achieve. I'm trying to use the transform right direction to offset the cue from the centre of the white ball to either side of the cue ball and then add the backwards transform direction of the cue to place it just behind the cue ball (see below). Additionally, I've avoided using transform.Translate(Vector3, Space.local) as I want to offset the cue with the values of -1 to 1.
Answer by notloop · Jan 23, 2019 at 01:07 PM
public void SetSpin(Vector2 spin)
{
// x = 1.0 right side
// x = -1.0 left side
// y = 1 top spin
// y = -1 back spin
float cueXSpinAmount = m_cueBallDistFromOriginToSide * Mathf.Clamp(spin.x, -1f, 1f);
float cueYSpinAmount = Mathf.Clamp(spin.y, -1f, 1f);
// Position cue behind the cue ball
transform.position = m_cueBallTrans.position + (-transform.forward.normalized * 0.8f);
// Reset y height in cue
transform.position = new Vector3(transform.position.x, 0f, transform.position.z);
// Translate the cue from the centre of the cue ball to the specified X spin amount
transform.Translate(cueXSpinAmount, 0f, 0f);
// Reset the X rotation of the cue
transform.rotation = Quaternion.Euler(0f, transform.rotation.eulerAngles.y , transform.rotation.eulerAngles.z);
// Rotate the cue in the x axis with the specified Y spin amount
transform.Rotate(new Vector3(-cueYSpinAmount, 0f, 0f));
}
I managed to get it working by resetting the cue each time I set the spin to the centre of the ball and then translate and rotate accordingly. I'm going to try and refactor to mitigate the need to reset the cue each time and not use transform.Translate and transform.Rotate and instead set the transform.position and transform.rotation directly.