[SOLVED] Help with setting up an endless twisting tower
Hi,
I wanted to make a game similar to Fuzion Frenzy's Twisted Sytems mini-game. In Twisted Systems four players are endlessly running around a spiralling tower and must duck and jump obstacles.
So I modelled a quick 3D tower. In Unity, I have it in three segments and moving downwards. Once a segment goes off screen it respawns back to the top of the stack. At this point when the tower respawns it instantiates either a duck or jump obstacle from an array at certain transform points around its neck.
I then tied the camera and the player to a central gameObject I called pivot that was at 0,0,0 in the centre of the tower. I made a rotation script on this. So the camera and player rotate around the tower. The tower at the moment does not rotate.
From here I created a GameManger that sat over all the gameobjects and could control the rotation speed of the pivot, and the downward descend speed of the tower.
But this quickly became way more complicated than I am capable of. No matter what I do I cannot get the descending speed of the tower and rotation of the player/camera to sync up. What I am aiming for is the camera and player to be fixed at the same point of the towers path descent (I hope I've explained that correctly, but identical to the first gif at the top of this question). I've tried lots of combinations (rotating the tower, making the player slowly rise up, etc) but I know it requires more thinking.
I started trying to place an inverted rotation on the player and camera that goes against the tower (using transform.rotation = Quaternion.Inverse(tower.rotation)), but this didn't work. And I have a feeling I'm into the place where I may have to use quarternions or some form of angles to be able to get the character and camera pivot to be inversely rotating against the towers descent. I know at the moment that I want the player and camera to be rotating, and it wouldn't be good to have the player actually climbing (given this is an endless runner).
Any suggestions on how I could implement this? Any replies really appreciated. Thank you.
UPDATE: SOLVED
After lots of reading around, I manage to solve this by diving into EulerAngles and Quaternion rotations.
private const int objHeight = 2;
public float speed = 2;
private void FixedUpdate()
{
transform.position += Vector3.down * speed * Time.fixedDeltaTime;
transform.rotation *= Quaternion.Euler(0, 360 / objHeight * speed * Time.fixedDeltaTime, 0);
}
Answer by Bunny83 · Jun 23, 2019 at 10:08 AM
Well, that's something you should have counted for when you created the spiral. If you know the exact height of one turn you can easily calculate the required rotation for a given descend / ascend speed.
Just assume the distance from one sprial to the other vertically is 4 units. That means you have to rotate the spiral at a rotational speed of
v*360°/4
where v is the vertical velocity. So as an example if as assumed the distance is 4 and you move the tower 1 unit per second downwards you need to rotate the tower 90° per second clockwise. Note that at the moment you seem to rotate your tower counter clockwise. A counter clockwise rotation would assume that your tower moves up instead of down. So you might just have the rotation the wrong way round?
I tried this approach but sadly it's not working correctly. The tower is spinning incredibly fast. I have the height of the tower model which is 30 units.
Since I'm using a transform move and not a rigidbody, I have to calculate the vertical velocity in a fixedUpdate. This is my code at the moment
public float speedDown;
public float speedRotate;
private Vector3 PrevPos;
private Vector3 NewPos;
private Vector3 ObjVelocity;
// Use this for initialization
void Start () {
PrevPos = transform.position;
NewPos = transform.position;
}
void FixedUpdate()
{
NewPos = transform.position;
ObjVelocity = (NewPos - PrevPos) / Time.fixedDeltaTime; // velocity = dist/time
PrevPos = NewPos;
}
void Update () {
speedRotate = ObjVelocity.y * 360 / 30;
transform.Rotate (0, speedRotate, 0 * Time.deltaTime); ;
transform.position += Vector3.down * Time.deltaTime * speedDown;
}
Well, first of all there is absolutely no reason why you need to "measure" the speed since you actually move your object at the given speed of "speedDown" units per second. If you don't use a rigidbody, stay away from FixedUpdate. Even when using a rigidbody there are only a few cases where you would need FixedUpdate.
Though the reason why you rotate way too fast is because you did not scale your rotation speed by deltaTime. Look at this line:
transform.Rotate (0, speedRotate, 0 * Time.deltaTime); ;
you only scale the 3rd parameter (which is 0) by Time.deltaTime which is pretty pointless. Just remove your FixedUpdate method completely. All you need is this:
public float speedDown;
public float verticalDistance = 30f;
void Update ()
{
transform.position += Vector3.down * Time.deltaTime * speedDown;
float speedRotate = speedDown * 360f / verticalDistance;
transform.Rotate (0, speedRotate * Time.deltaTime, 0);
}
Are you actually sure about the 30 units? 30 units is quite a lot in Unity. Usually 1 unit is considered 1 meter. Of course it's all just a matter of scale. If the capsule that is visible in your image is a normal sized capsule it would be 2 units high. It doesn't look like you get 15 of those capsules between two layers. Just make sure you actually work with the correct numbers.
Answer by EstragonHelmer · Jun 23, 2019 at 10:09 AM
This is all off the top of my head, I haven't tested it, but I think it should be correct. It's essentially a maths problem.
You need to know how often it rotates a full 360 degrees.
You need to know the vertical distance between the platform, and the next bit above it.
You need to drop down by that height in the same amount of time as 1 full 360 rotation takes.
So, say your platforms are 1 unit apart. And your full rotation takes 5 seconds. You'd need to drop down by 1 unit every 5 seconds, so move at 0.2 * time.deltaTime
Your answer
Follow this Question
Related Questions
Look Left or right but keep walking forward 0 Answers
endless runner rotating 0 Answers
Cancel out the steering rotation returned from a wheel colliders .GetWorldPose(out pos, out rot); 1 Answer
Space/Aircraft rotation 0 Answers
Camera Controller script as a child object,Camera Control as a Child Object for my Player 0 Answers