Post by sickscore on Feb 20, 2017 14:18:01 GMT
FLY SYSTEM
FLY LIKE AN EAGLE WITHOUT REDBULL :D
-- DEMO SCENE NOT INCLUDED --
Hey guys,
as many of you have requested, now you can finally fly over the clouds and further.
Please let me know, if you like it and don't hesitate to report issues.
I'll continue to work on this addon to improve it over time, so stay tuned!
Cheers, sickscore
FEATURES:
- Default falling/landing animations when out of stamina/grounded/crash-landed
- Stamina consumption for flying / floating mid-air
- Controllable forward and up/down force
- Custom collider size for flying state
- Free mocap animations included
- ..etc..
HOW TO USE:
- Press "X" while jumping to enter flying state.
- Hold down "space" or "left shift" to fly upwards/downwards
=> You can change the keybinds in the Invector input manager
INSTRUCTIONS:
1. Download unitypackage with free mocap animations and a template how to setup the animator controller -> DOWNLOAD
2. Backup original files and apply the code changes from below
KNOWN BUGS:
- T.B.A.
== ANIMATOR OVERVIEW ==
>> Animator controller template is included in the unitypackage download! <<
>> Animator controller template is included in the unitypackage download! <<
== CODE CHANGES BELOW ==
>> Don't forget to make a backup before editing! <<
>> Don't forget to make a backup before editing! <<
vThirdPersonInput.cs
Add 3 additional GenericInputs under Variables => Default Inputs
public GenericInput flyInput = new GenericInput("X", "X", "X");
public GenericInput flyUpInput = new GenericInput("Space", "X", "X");
public GenericInput flyDownInput = new GenericInput("LeftShift", "X", "X");
Add FlyAirControl method call to FixedUpdate after cc.AirControl()
cc.FlyAirControl ();
Add FlyInput method call after JumpInput()
FlyInput ();
Add FlyInput method (after JumpInput method = line 240)
protected virtual void FlyInput ()
{
if (flyInput.GetButtonDown ())
cc.Fly ();
if (flyUpInput.GetButton ()) {
cc.ChangeFlyDirection (1);
} else if (flyDownInput.GetButton ()) {
cc.ChangeFlyDirection (-1);
} else {
cc.ChangeFlyDirection (0);
}
}
vThirdPersonController.cs
Add Fly method (after Jump method = line 98)
public virtual void Fly ()
{
// Toggle flying
if (isFlying) {
isFlying = false;
animator.SetBool("IsFlying", isFlying);
_rigidbody.useGravity = true;
return;
}
if (animator.IsInTransition (0))
return;
// know if has enough stamina to make this action
bool staminaConditions = currentStamina > flyStaminaMove;
// conditions to do this action
bool flyConditions = !isCrouching && !actions && !isGrounded && staminaConditions;
// return if flyConditions is false
if (!flyConditions)
return;
// trigger fly behaviour
isFlying = true;
isJumping = false;
// trigger fly animations
animator.SetBool("IsFlying", isFlying);
}
vThirdPersonMotor.cs
Add variables under Variables => Stamina Consumption after jumpStamina
[SerializeField]
protected float flyStaminaIdle = 0f;
[SerializeField]
protected float flyStaminaMove = 10f;
Add "Fly Options" under "Jump Options"
[Header("Fly Options")]
[Tooltip("Add extra fly speed, based on your speed input the character will fly forward")]
public float flyForward = 12f;
[Tooltip("Force applied to the rigidbody when flying up/down")]
public float flyUpDownForce = 30f;
[Tooltip("Transition lerp speed between up/down movement")]
public float flyForceLerp = 3f;
[Tooltip("(optional) Change collider size when flying. Should be fine for most characters")]
public float flyColliderRadius = .5f;
protected int flyUpDownChange;
protected int lastFlyUpDownChange;
protected bool flyDirectionChanged;
Add new action to "action bools"
isFlying
Add ControlFlyBehaviour method to UpdateMotor() method
ControlFlyBehaviour();
Add lines to CheckStamina() method after isSprinting check
if (isFlying)
{
currentStaminaRecoveryDelay = .5f;
float flyStamina = (speed > .1f || flyUpDownChange != 0) ? flyStaminaMove : flyStaminaIdle;
ReduceStamina(flyStamina, true);
}
Change first line of AirControl() method
if (isGrounded || isFlying) return;
Add region "Fly Methods" between region "Jump Methods" and region "Ground Check"
#region Fly Methods
protected void ControlFlyBehaviour()
{
if (!isFlying) return;
// check flight stamina
bool outOfStamina = false;
if (currentStamina <= 0f)
outOfStamina = (speed >= 0.1f || flyUpDownChange != 0) ? (flyStaminaMove > 0f) : flyStaminaIdle > 0f;
// interrupt flying when out of stamina or grounded / crash-landed :)
if (outOfStamina || isGrounded && isFlying) {
isFlying = false;
animator.SetBool("IsFlying", isFlying);
_rigidbody.useGravity = true;
return;
}
// disable gravity
_rigidbody.useGravity = false;
// add force depending on direction
if (flyUpDownChange != 0) {
float flyVel = (flyUpDownChange > 0) ? flyUpDownForce : -flyUpDownForce;
_rigidbody.AddForce (transform.up * flyVel * Time.deltaTime, ForceMode.VelocityChange);
}
// lerp velocity for a smoother flight
bool directionResetCondition = flyUpDownChange == 0 && _rigidbody.velocity.y != 0f;
bool directionChangeCondition = lastFlyUpDownChange != flyUpDownChange;
if (directionResetCondition || directionChangeCondition) {
Vector3 currentVel = _rigidbody.velocity;
currentVel.y = Mathf.Lerp (currentVel.y, 0f, flyForceLerp * Time.deltaTime);
_rigidbody.velocity = currentVel;
}
}
/// <summary>
/// Used to define up/down movement while mid-air
/// </summary>
/// <param name="_direction">1 = UP | -1 = DOWN | 0 = STRAIGHT</param>
public void ChangeFlyDirection (int _direction)
{
// reset direction
if (_direction == 0) {
flyDirectionChanged = false;
flyUpDownChange = 0;
return;
}
// check if direction has changed
if (lastFlyUpDownChange != _direction) {
if (!flyDirectionChanged) {
flyDirectionChanged = true;
lastFlyUpDownChange = flyUpDownChange;
}
}
// apply new direction
flyUpDownChange = _direction;
}
public void FlyAirControl()
{
if (isGrounded || !isFlying) return;
var vel = transform.forward * flyForward * speed;
vel.y = _rigidbody.velocity.y;
_rigidbody.velocity = Vector3.Lerp (_rigidbody.velocity, vel, 4f * Time.deltaTime);
if (isStrafing)
{
_rigidbody.AddForce(transform.forward * (flyForward * speed) * Time.deltaTime, ForceMode.VelocityChange);
_rigidbody.AddForce(transform.right * (flyForward * direction) * Time.deltaTime, ForceMode.VelocityChange);
}
else
{
_rigidbody.AddForce(transform.forward * (flyForward * speed) * Time.deltaTime, ForceMode.VelocityChange);
}
}
#endregion
Update last IF-statement in GroundCheck() method (add "&& !isFlying" before each _rigidbody.AddForce line)
if (groundDistance >= groundCheckDistance)
{
isGrounded = false;
// check vertical velocity
verticalVelocity = _rigidbody.velocity.y;
// apply extra gravity when falling
if (!onStep && !isJumping && !isFlying)
_rigidbody.AddForce(transform.up * extraGravity * Time.deltaTime, ForceMode.VelocityChange);
}
else if (!onStep && !isJumping && !isFlying)
{
_rigidbody.AddForce(transform.up * (extraGravity * 2) * Time.deltaTime, ForceMode.VelocityChange);
}
Replace/update ControlCapsuleHeight() method
void ControlCapsuleHeight()
{
if (isCrouching || isRolling || landHigh)
{
_capsuleCollider.center = colliderCenter / 1.4f;
_capsuleCollider.height = colliderHeight / 1.4f;
}
else if (isUsingLadder)
{
_capsuleCollider.radius = colliderRadius / 1.25f;
}
else if (isFlying)
{
_capsuleCollider.radius = flyColliderRadius;
_capsuleCollider.height = flyColliderRadius;
}
else
{
// back to the original values
_capsuleCollider.center = colliderCenter;
_capsuleCollider.radius = colliderRadius;
_capsuleCollider.height = colliderHeight;
}
}