Hello everyone.
I’ve been scratching my head about this for a month now. How can I achieve a movement like the one here?
There’s a cylinder, and the object sticks to the interior walls, effectively performing a 360 degree spin. Also, there’s the issue of the cylinder bending in some parts, so it’s effectively a magnetic field holding the object down (or up, or whichever way).
Which objects are you talking about? Obstacles or the player?
The obstacles look like they’re a child of the tunnel. The player meanwhile either has something moving him down continuously kinda like gravity, or the player is positioned to be a specific distance from the tunnel’s center. There could be a spline that runs down the center of the tunnel that can be used to position things a certain distance from the center.
As for rotations…
I’m pretty sure there’s something representing the middle of the tunnel, even if it’s not visible. The middle would be a line or a spline. You could rotate the player around using Transform.RotateAround() with the center line/spline as the axis of rotation.
I might try with Transform.RotateAround() for the player. Mind if I keep the thread for prototyping?
Feel free to keep the thread open, though you might get quicker and better answers by making a new concise topic for each specific problem you run into. Whatever works best for you!
I did something like this recently with my internal colony prototype for High Frontier.
This works by just beating the position and rotation into submission with math every frame. That is, I know that the camera is supposed to be a certain distance from the cylinder axis, and its “up” vector is supposed to point at the cylinder axis, so I just force it to the closest position/orientation that satisfies those constraints. Here’s the code, in case there’s anything useful in it for you:
using UnityEngine;
using System.Collections;
public class CylinderCamControl : MonoBehaviour {
public float radius = 147;
public float turnSpeed = 150;
public float forwardSpeed = 10;
void Update() {
float boost = 1f;
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) boost = 5f;
transform.Rotate(0f, Input.GetAxis("Mouse X") * turnSpeed * Time.deltaTime, 0f);
transform.position += transform.forward * Input.GetAxis("Vertical")
* forwardSpeed * boost * Time.deltaTime;
Snap();
}
void OnGUI() {
if (Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)) {
Rect r = new Rect(20, Screen.height-40, 100, 20);
GUI.Label(r, "Super Speed");
}
}
void Snap() {
Vector3 pos = transform.position;
float ang = Mathf.Atan2(pos.z, pos.x);
Vector3 lookDir = transform.forward;
pos.x = Mathf.Cos(ang) * radius;
pos.z = Mathf.Sin(ang) * radius;
transform.position = pos;
Vector3 properUp = new Vector3(-pos.x, 0, -pos.z);
Vector3 properLook = ProjectVectorOnPlane(properUp, lookDir);
transform.rotation = Quaternion.LookRotation(properLook, properUp);
}
//Projects a vector onto a plane. The output is not normalized.
static Vector3 ProjectVectorOnPlane(Vector3 planeNormal, Vector3 vector) {
planeNormal.Normalize();
return vector - (Vector3.Dot(vector, planeNormal) * planeNormal);
}
}
Alright, I made a little bit of progress.
http://labs.marcoff-weyland.com/BLS/BLD.html
Unfortunately, as you can see, the player only rotates to 90 degrees, -90 respectively, then stops. The forward/backward is broken, because it doesn’t take into consideration the raycast.
Here’s the movement code:
using UnityEngine;
using System.Collections;
using System;
public class PlayerMovement : MonoBehaviour {
public float Speed = 0;
public float MaxSpeed = 1;
public float rotationSpeed = 10;
public float Acceleration = 10;
public float Deceleration = 10;
public Transform target;
public float degrees = 10;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if ((Input.GetKey ("w")) && (Speed < MaxSpeed))
Speed = Speed - Acceleration * Time.deltaTime;
else if ((Input.GetKey ("a")) && (Speed > -MaxSpeed))
Speed = Speed + Acceleration * Time.deltaTime;
else {
if (Speed > Deceleration * Time.deltaTime)
Speed = Speed - Deceleration * Time.deltaTime;
else if (Speed < -Deceleration * Time.deltaTime)
Speed = Speed + Deceleration * Time.deltaTime;
else
Speed = 0;
}
transform.position = new Vector3 (transform.position.x, transform.position.y, transform.position.z + Speed * Time.deltaTime);
RaycastHit rcHit;
Vector3 theRay = transform.TransformDirection(-Vector3.up);
if (Physics.Raycast(transform.position, theRay, out rcHit))
{
float groundDis = rcHit.distance;
transform.rotation = Quaternion.FromToRotation(Vector3.up,rcHit.normal);
float movement = Input.GetAxis("Horizontal") * rotationSpeed * Time.deltaTime;
transform.localPosition =
new Vector3(transform.localPosition.x + movement, (transform.localPosition.y - groundDis)+.2f, transform.localPosition.z);
}
}
}