I’ve a clean 6DoF controller from following a tutorial (that is the tutorial) and tweaked it to be precisely what I would like with a couple of exceptions.
I discovered myself wanting the flexibility to lock the horizon line by urgent a toggle button so whereas the participant is freely rotating across the horizon stays degree till the lock is disabled.
I might additionally wish to have a button that easily rotates the horizon to be degree with the Ship object/digicam however preserve the yaw and pitch the identical. I am undecided how it could work however I would like this button to easily easily upright the Ship when the button is pressed as soon as and have the horizon lock be a separate non-obligatory function.
I don’t know the place to even begin on the mathematics/logic for these two options however I’ve the buttons and features mapped already hoping I’d simply gleam somebody’s smarter code and simply having it magically work ultimately. I’ve a sense there’s a greater manner of going about this than guessing or trial and error haha.
The complete script for the Ship object is self-contained and I will put it right here together with some photographs and GIFs of assorted hopefully helpful particulars.
As an apart, I am certain there is a easy answer I am overlooking however the ship does roll when colliding with different objects (spherical collision mesh). Is there a strategy to both disable it or have much less friction?
utilizing System.Collections;
utilizing System.Collections.Generic;
utilizing UnityEngine;
utilizing UnityEngine.InputSystem;
[RequireComponent (typeof(Rigidbody))]
public class Ship : MonoBehaviour
{
// Parameters
[Header("=== Ship Movement Settings ===")]
[SerializeField]
non-public float pitchTorque = 500f;
[SerializeField]
non-public float yawTorque = 1000f;
[SerializeField]
non-public float rollTorque = 1000f;
[SerializeField]
non-public float thrust = 100f;
[SerializeField]
non-public float strafeThrust = 50f;
[SerializeField]
non-public float verticalThrust = 50f;
public bool horizonLock = false;
[Header("=== Boost Settings ===")]
[SerializeField]
non-public float boostMultiplier = 5f;
[Header("=== Thrust Reduction Settings ===")]
[SerializeField]
non-public float drag = 1f;
[SerializeField]
non-public float angularDrag = 0.5f;
[SerializeField, Range(0.001f, 0.999f)]
non-public float thrustGlideReduction = 0.9f;
[SerializeField, Range(0.001f, 0.999f)]
non-public float strafeGlideReduction = 0.1f;
[SerializeField, Range(0.001f, 0.999f)]
non-public float verticalGlideReduction = 0.1f;
// Variables
Rigidbody rb;
float glide = 0f;
float strafeGlide = 0f;
float verticalGlide = 0f;
bool boosting = false;
bool altMove = false;
bool altRoll = false;
bool cease = false;
bool autoUpright = false;
// Enter Values
non-public float thrust1D;
non-public float strafe1D;
non-public float vertical1D;
non-public float roll1D;
non-public Vector2 pitchYaw;
// Begin is known as earlier than the primary body replace
void Begin()
{
rb = GetComponent<Rigidbody>();
}
// Replace is known as as soon as per body
void FixedUpdate()
{
HandleMovement();
}
void HandleMovement()
{
/* The explanation for all of the altRoll and altMove statements is to have alternate momentary
* manner of shifting and rolling the ship.
*
* AltMove shifts horizontal and ahead/backward motion inputs to vertical/horizontal motion.
* It additionally shifts vertical motion inputs to ahead/backward motion.
*
* AltRoll shifts the yaw/pitch motion inputs to roll/pitch.
* It additionally maps roll inputs to yaw for comfort.
*/
// Roll
if(!altRoll) rb.AddRelativeTorque(Vector3.again * roll1D * rollTorque * Time.deltaTime);
else rb.AddRelativeTorque(Vector3.again * Mathf.Clamp(pitchYaw.x, -1f, 1f) * rollTorque * Time.deltaTime);
// Pitch
rb.AddRelativeTorque(Vector3.proper * Mathf.Clamp(-pitchYaw.y, -1f, 1f) * pitchTorque * Time.deltaTime);
// Yaw
if (!altRoll) rb.AddRelativeTorque(Vector3.up * Mathf.Clamp(pitchYaw.x, -1f, 1f) * yawTorque * Time.deltaTime);
else rb.AddRelativeTorque(Vector3.up * roll1D * yawTorque * Time.deltaTime);
// Thrust
if (!altMove && (thrust1D > 0.1f || thrust1D < -0.1f))
{
float currentThrust;
if (boosting) currentThrust = thrust * boostMultiplier;
else currentThrust = thrust;
rb.AddRelativeForce(Vector3.ahead * thrust1D * currentThrust * Time.deltaTime);
glide = thrust;
}
else if(altMove && (vertical1D > 0.1f || vertical1D < -0.1f))
{
float currentThrust;
if (boosting) currentThrust = thrust * boostMultiplier;
else currentThrust = thrust;
rb.AddRelativeForce(Vector3.ahead * vertical1D * currentThrust * Time.deltaTime);
glide = thrust;
}
else
{
rb.AddRelativeForce(Vector3.ahead * glide * Time.deltaTime);
glide *= thrustGlideReduction;
}
// Strafe
if (strafe1D > 0.1f || strafe1D < -0.1f)
{
float currentThrust;
if (boosting) currentThrust = thrust * boostMultiplier;
else currentThrust = thrust;
rb.AddRelativeForce(Vector3.proper * strafe1D * currentThrust * Time.deltaTime);
strafeGlide = strafe1D * strafeThrust;
}
else
{
rb.AddRelativeForce(Vector3.proper * strafeGlide * Time.deltaTime);
strafeGlide *= strafeGlideReduction;
}
// Vertical
if (!altMove && (vertical1D > 0.1f || vertical1D < -0.1f))
{
float currentThrust;
if (boosting) currentThrust = thrust * boostMultiplier;
else currentThrust = thrust;
rb.AddRelativeForce(Vector3.up * vertical1D * currentThrust * Time.deltaTime);
verticalGlide = vertical1D * verticalThrust;
}
else if (altMove && (thrust1D > 0.1f || thrust1D < -0.1f))
{
float currentThrust;
if (boosting) currentThrust = thrust * boostMultiplier;
else currentThrust = thrust;
rb.AddRelativeForce(Vector3.up * thrust1D * currentThrust * Time.deltaTime);
verticalGlide = thrust1D * verticalThrust;
}
else
{
rb.AddRelativeForce(Vector3.up * verticalGlide * Time.deltaTime);
verticalGlide *= verticalGlideReduction;
}
// What I name the "cease on a dime" button. Momentarily will increase drag to freeze the ship in place.
if (cease)
{
rb.drag = 50;
rb.angularDrag = 50;
}
else
{
rb.drag = drag;
rb.angularDrag = angularDrag;
}
}
// Enter handlers
#area Enter Strategies
public void OnThrust(InputAction.CallbackContext context)
{
thrust1D = context.ReadValue<float>();
}
public void OnStrafe(InputAction.CallbackContext context)
{
strafe1D = context.ReadValue<float>();
}
public void OnVertical(InputAction.CallbackContext context)
{
vertical1D = context.ReadValue<float>();
}
public void OnRoll(InputAction.CallbackContext context)
{
roll1D = context.ReadValue<float>();
}
public void OnPitchYaw(InputAction.CallbackContext context)
{
pitchYaw = context.ReadValue<Vector2>();
}
public void OnBoost(InputAction.CallbackContext context)
{
boosting = context.carried out;
}
public void OnAltMove(InputAction.CallbackContext context)
{
altMove = context.carried out;
}
public void OnAltRoll(InputAction.CallbackContext context)
{
altRoll = context.carried out;
}
public void OnStop(InputAction.CallbackContext context)
{
cease = context.carried out;
}
public void OnHorizonLock(InputAction.CallbackContext context)
{
horizonLock = !horizonLock;
}
public void OnAutoUpright(InputAction.CallbackContext context)
{
autoUpright = context.carried out;
}
#endregion
}
Inspector Window for the Ship object.