812 lines
27 KiB
C#
812 lines
27 KiB
C#
|
|
using UnityEngine;
|
|||
|
|
using System.Collections;
|
|||
|
|
using System;
|
|||
|
|
|
|||
|
|
public class upperBodyRotationSystem : MonoBehaviour
|
|||
|
|
{
|
|||
|
|
[Header ("Main Settings")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public bool shakeUpperBodyEnabled = true;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Header ("Head Settings")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public Vector3 headLookVector = Vector3.forward;
|
|||
|
|
public Vector3 headUpVector = Vector3.up;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Header ("Rotation Settings")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public float horizontalThresholdAngleDifference = 5;
|
|||
|
|
public float verticalThresholdAngleDifference = 5;
|
|||
|
|
public float horizontalBendingMultiplier = 1;
|
|||
|
|
public float verticalBendingMultiplier = 1;
|
|||
|
|
public float horizontalMaxAngleDifference = 90;
|
|||
|
|
public float verticalMaxAngleDifference = 90;
|
|||
|
|
public float maxBendingAngle = 90;
|
|||
|
|
public float horizontalResponsiveness = 10;
|
|||
|
|
public float verticalResponsiveness = 10;
|
|||
|
|
|
|||
|
|
public float upperBodyRotationSpeed = 5;
|
|||
|
|
public float rotationSpeed = 5;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public bool chestRotationEnabled = true;
|
|||
|
|
public bool spineRotationEnabled = true;
|
|||
|
|
public bool extraHorizontalRotationEnabled = true;
|
|||
|
|
|
|||
|
|
public bool horizontalRotationEnabled = true;
|
|||
|
|
public bool verticalRotationEnabled = true;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public bool useSmoothRotationPointValue;
|
|||
|
|
public float smoothRotationPointValue = 0.1f;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Header ("Chest Orientation Settings")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public Vector3 chestUpVector = new Vector3 (0, 0, 1);
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Header ("Spine And Chest Transforms")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public Transform spineTransform;
|
|||
|
|
public Transform chestTransform;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Header ("Other Settings")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public bool followFullRotationPointDirection;
|
|||
|
|
|
|||
|
|
public Vector3 followFullRotationPointMultipliers = Vector3.one;
|
|||
|
|
|
|||
|
|
public bool useFollowFullRotationClamp;
|
|||
|
|
|
|||
|
|
public Vector2 followFullRotationClampX;
|
|||
|
|
public Vector2 followFullRotationClampY;
|
|||
|
|
public Vector2 followFullRotationClampZ;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Header ("Debug")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public bool IKUpperBodyActive;
|
|||
|
|
public float currentExtraRotation;
|
|||
|
|
public bool usingWeaponRotationPoint;
|
|||
|
|
|
|||
|
|
public bool usingTemporalObjectToFollow;
|
|||
|
|
public Transform temporalObjectToFollow;
|
|||
|
|
|
|||
|
|
public Transform currentWeaponRotationPoint;
|
|||
|
|
|
|||
|
|
public bool fullBodyAwarenessActive;
|
|||
|
|
|
|||
|
|
[Space]
|
|||
|
|
[Header ("Components")]
|
|||
|
|
[Space]
|
|||
|
|
|
|||
|
|
public Transform objectToFollow;
|
|||
|
|
public Transform weaponRotationPointToFollow;
|
|||
|
|
public playerController playerControllerManager;
|
|||
|
|
|
|||
|
|
|
|||
|
|
bool usingDualWeapon;
|
|||
|
|
|
|||
|
|
|
|||
|
|
|
|||
|
|
float currentRotation;
|
|||
|
|
float rotationXValue;
|
|||
|
|
|
|||
|
|
weaponRotationPointInfo rotationPointInfo;
|
|||
|
|
|
|||
|
|
int currentRotationDirection = 1;
|
|||
|
|
|
|||
|
|
Quaternion chestRotation;
|
|||
|
|
Quaternion spineRotation;
|
|||
|
|
|
|||
|
|
float angleH;
|
|||
|
|
float angleV;
|
|||
|
|
Vector3 dirUp;
|
|||
|
|
Vector3 referenceLookDir;
|
|||
|
|
Vector3 referenceUpDir;
|
|||
|
|
float originalAngleDifference;
|
|||
|
|
Coroutine changeExtraRotation;
|
|||
|
|
|
|||
|
|
Vector3 extraRotation;
|
|||
|
|
|
|||
|
|
float auxCurrentExtraRotation;
|
|||
|
|
|
|||
|
|
Coroutine shakeUpperBodyRotationCoroutine;
|
|||
|
|
|
|||
|
|
Quaternion parentRot;
|
|||
|
|
Quaternion parentRotInv;
|
|||
|
|
Vector3 lookDirWorld;
|
|||
|
|
Vector3 lookDirGoal;
|
|||
|
|
|
|||
|
|
Vector3 rightOfTarget;
|
|||
|
|
Vector3 lookDirGoalinHPlane;
|
|||
|
|
|
|||
|
|
float hAngle;
|
|||
|
|
float vAngle;
|
|||
|
|
float hAngleThr;
|
|||
|
|
float vAngleThr;
|
|||
|
|
|
|||
|
|
float hAngleABS;
|
|||
|
|
float vAngleABS;
|
|||
|
|
|
|||
|
|
float hAngleSign;
|
|||
|
|
float vAngleSign;
|
|||
|
|
|
|||
|
|
Vector3 referenceRightDir;
|
|||
|
|
Vector3 upDirGoal;
|
|||
|
|
Vector3 lookDir;
|
|||
|
|
Quaternion lookRot;
|
|||
|
|
Quaternion dividedRotation;
|
|||
|
|
|
|||
|
|
Quaternion finalLookRotation;
|
|||
|
|
|
|||
|
|
bool isPlayerDead;
|
|||
|
|
|
|||
|
|
Transform currentRightWeaponRotationPoint;
|
|||
|
|
Transform currentLeftWeaponRotationPoint;
|
|||
|
|
|
|||
|
|
weaponRotationPointInfo rightRotationPointInfo;
|
|||
|
|
weaponRotationPointInfo leftRotationPointInfo;
|
|||
|
|
|
|||
|
|
int currentRightRotationDirection = 1;
|
|||
|
|
int currentLeftRotationDirection = 1;
|
|||
|
|
|
|||
|
|
bool weaponRotationPointToFollowLocated;
|
|||
|
|
|
|||
|
|
float originalHorizontalBendingMultiplier;
|
|||
|
|
float originalVerticalBendingMultiplier;
|
|||
|
|
|
|||
|
|
float originalHorizontalMaxAngleDifference;
|
|||
|
|
float originalVerticalMaxAngleDifference;
|
|||
|
|
|
|||
|
|
float currentTime;
|
|||
|
|
|
|||
|
|
float currentDeltatime;
|
|||
|
|
|
|||
|
|
void Start ()
|
|||
|
|
{
|
|||
|
|
parentRot = spineTransform.parent.rotation;
|
|||
|
|
parentRotInv = Quaternion.Inverse (parentRot);
|
|||
|
|
|
|||
|
|
referenceLookDir = parentRotInv * transform.rotation * headLookVector.normalized;
|
|||
|
|
referenceUpDir = parentRotInv * transform.rotation * headUpVector.normalized;
|
|||
|
|
dirUp = referenceUpDir;
|
|||
|
|
originalAngleDifference = maxBendingAngle;
|
|||
|
|
|
|||
|
|
weaponRotationPointToFollowLocated = weaponRotationPointToFollow != null;
|
|||
|
|
|
|||
|
|
originalHorizontalBendingMultiplier = horizontalBendingMultiplier;
|
|||
|
|
originalVerticalBendingMultiplier = verticalBendingMultiplier;
|
|||
|
|
|
|||
|
|
originalHorizontalMaxAngleDifference = horizontalMaxAngleDifference;
|
|||
|
|
originalVerticalMaxAngleDifference = verticalMaxAngleDifference;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void FixedUpdate ()
|
|||
|
|
{
|
|||
|
|
if (IKUpperBodyActive) {
|
|||
|
|
|
|||
|
|
isPlayerDead = playerControllerManager.isPlayerDead ();
|
|||
|
|
|
|||
|
|
if (isPlayerDead) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
currentTime = Time.smoothDeltaTime;
|
|||
|
|
|
|||
|
|
parentRot = spineTransform.parent.rotation;
|
|||
|
|
parentRotInv = Quaternion.Inverse (parentRot);
|
|||
|
|
|
|||
|
|
// Desired look direction in world space
|
|||
|
|
if (usingTemporalObjectToFollow) {
|
|||
|
|
lookDirWorld = (temporalObjectToFollow.position - chestTransform.position).normalized;
|
|||
|
|
} else {
|
|||
|
|
lookDirWorld = (objectToFollow.position - chestTransform.position).normalized;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Desired look directions in neck parent space
|
|||
|
|
lookDirGoal = (parentRotInv * lookDirWorld);
|
|||
|
|
|
|||
|
|
// Get the horizontal and vertical rotation angle to look at the target
|
|||
|
|
hAngle = AngleAroundAxis (referenceLookDir, lookDirGoal, referenceUpDir);
|
|||
|
|
|
|||
|
|
rightOfTarget = Vector3.Cross (referenceUpDir, lookDirGoal);
|
|||
|
|
lookDirGoalinHPlane = lookDirGoal - Vector3.Project (lookDirGoal, referenceUpDir);
|
|||
|
|
|
|||
|
|
vAngle = AngleAroundAxis (lookDirGoalinHPlane, lookDirGoal, rightOfTarget);
|
|||
|
|
|
|||
|
|
|
|||
|
|
hAngleABS = Mathf.Abs (hAngle);
|
|||
|
|
vAngleABS = Mathf.Abs (vAngle);
|
|||
|
|
|
|||
|
|
hAngleSign = Mathf.Sign (hAngle);
|
|||
|
|
vAngleSign = Mathf.Sign (vAngle);
|
|||
|
|
|
|||
|
|
|
|||
|
|
// Handle threshold angle difference, bending multiplier, and max angle difference here
|
|||
|
|
hAngleThr = Mathf.Max (0, hAngleABS - horizontalThresholdAngleDifference) * hAngleSign;
|
|||
|
|
vAngleThr = Mathf.Max (0, vAngleABS - verticalThresholdAngleDifference) * vAngleSign;
|
|||
|
|
|
|||
|
|
hAngle = Mathf.Max (Mathf.Abs (hAngleThr) * Mathf.Abs (horizontalBendingMultiplier), hAngleABS
|
|||
|
|
- horizontalMaxAngleDifference) * hAngleSign * Mathf.Sign (horizontalBendingMultiplier);
|
|||
|
|
|
|||
|
|
vAngle = Mathf.Max (Mathf.Abs (vAngleThr) * Mathf.Abs (verticalBendingMultiplier), vAngleABS
|
|||
|
|
- verticalMaxAngleDifference) * vAngleSign * Mathf.Sign (verticalBendingMultiplier);
|
|||
|
|
|
|||
|
|
// Handle max bending angle here
|
|||
|
|
hAngle = Mathf.Clamp (hAngle, -maxBendingAngle, maxBendingAngle);
|
|||
|
|
vAngle = Mathf.Clamp (vAngle, -maxBendingAngle, maxBendingAngle);
|
|||
|
|
|
|||
|
|
referenceRightDir = Vector3.Cross (referenceUpDir, referenceLookDir);
|
|||
|
|
|
|||
|
|
// Lerp angles
|
|||
|
|
angleH = Mathf.Lerp (angleH, hAngle, currentTime * horizontalResponsiveness);
|
|||
|
|
angleV = Mathf.Lerp (angleV, vAngle, currentTime * verticalResponsiveness);
|
|||
|
|
|
|||
|
|
if (!horizontalRotationEnabled) {
|
|||
|
|
angleH = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!verticalRotationEnabled) {
|
|||
|
|
angleV = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Get direction
|
|||
|
|
lookDirGoal = Quaternion.AngleAxis (angleH, referenceUpDir) *
|
|||
|
|
Quaternion.AngleAxis (angleV, referenceRightDir) *
|
|||
|
|
referenceLookDir;
|
|||
|
|
|
|||
|
|
// Make look and up perpendicular
|
|||
|
|
upDirGoal = referenceUpDir;
|
|||
|
|
Vector3.OrthoNormalize (ref lookDirGoal, ref upDirGoal);
|
|||
|
|
|
|||
|
|
// Interpolated look and up directions in neck parent space
|
|||
|
|
lookDir = lookDirGoal;
|
|||
|
|
dirUp = Vector3.Slerp (dirUp, upDirGoal, currentTime * 5);
|
|||
|
|
Vector3.OrthoNormalize (ref lookDir, ref dirUp);
|
|||
|
|
|
|||
|
|
// Look rotation in world space
|
|||
|
|
lookRot = ((parentRot * Quaternion.LookRotation (lookDir, dirUp)) *
|
|||
|
|
Quaternion.Inverse (parentRot * Quaternion.LookRotation (referenceLookDir, referenceUpDir)));
|
|||
|
|
|
|||
|
|
if (upperBodyRotationSpeed > 0) {
|
|||
|
|
finalLookRotation = Quaternion.Slerp (finalLookRotation, lookRot, currentTime * upperBodyRotationSpeed);
|
|||
|
|
} else {
|
|||
|
|
finalLookRotation = lookRot;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Distribute rotation over all joints in segment
|
|||
|
|
dividedRotation = Quaternion.Slerp (Quaternion.identity, finalLookRotation, 0.5f);
|
|||
|
|
|
|||
|
|
chestRotation = dividedRotation;
|
|||
|
|
spineRotation = dividedRotation;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (usingWeaponRotationPoint) {
|
|||
|
|
checkWeaponRotationPoint ();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void LateUpdate ()
|
|||
|
|
{
|
|||
|
|
if (IKUpperBodyActive) {
|
|||
|
|
|
|||
|
|
if (!isPlayerDead) {
|
|||
|
|
if (chestRotationEnabled) {
|
|||
|
|
chestTransform.rotation = chestRotation * chestTransform.rotation;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (spineRotationEnabled) {
|
|||
|
|
spineTransform.rotation = spineRotation * spineTransform.rotation;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (extraHorizontalRotationEnabled) {
|
|||
|
|
if (currentExtraRotation != 0) {
|
|||
|
|
extraRotation = chestUpVector * currentExtraRotation;
|
|||
|
|
|
|||
|
|
chestTransform.localEulerAngles = new Vector3 (chestTransform.localEulerAngles.x, chestTransform.localEulerAngles.y, chestTransform.localEulerAngles.z) + extraRotation;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void checkWeaponRotationPoint ()
|
|||
|
|
{
|
|||
|
|
currentDeltatime = Time.smoothDeltaTime;
|
|||
|
|
|
|||
|
|
if (IKUpperBodyActive && weaponRotationPointToFollowLocated) {
|
|||
|
|
currentRotation = weaponRotationPointToFollow.localEulerAngles.x;
|
|||
|
|
|
|||
|
|
if (usingDualWeapon) {
|
|||
|
|
if (currentRightWeaponRotationPoint != null) {
|
|||
|
|
if (followFullRotationPointDirection) {
|
|||
|
|
updateFullRotationPoint (weaponRotationPointToFollow, currentRightWeaponRotationPoint,
|
|||
|
|
rightRotationPointInfo.rotationPointSpeed, currentDeltatime);
|
|||
|
|
} else {
|
|||
|
|
if (currentRotation > 180) {
|
|||
|
|
rotationXValue = (360 - currentRotation) / rightRotationPointInfo.rotationUpPointAmountMultiplier;
|
|||
|
|
|
|||
|
|
if (rightRotationPointInfo.useRotationUpClamp) {
|
|||
|
|
rotationXValue = Mathf.Clamp (rotationXValue, 0, rightRotationPointInfo.rotationUpClampAmount);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rotationXValue *= (-1) * currentRightRotationDirection;
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
rotationXValue = currentRotation / rightRotationPointInfo.rotationDownPointAmountMultiplier;
|
|||
|
|
|
|||
|
|
if (rightRotationPointInfo.useRotationDownClamp) {
|
|||
|
|
rotationXValue = Mathf.Clamp (rotationXValue, 0, rightRotationPointInfo.rotationDownClamp);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rotationXValue *= currentRightRotationDirection;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Quaternion weaponRotationPointTarget = Quaternion.Euler (new Vector3 (rotationXValue, 0, 0));
|
|||
|
|
|
|||
|
|
currentRightWeaponRotationPoint.localRotation =
|
|||
|
|
Quaternion.Lerp (currentRightWeaponRotationPoint.localRotation, weaponRotationPointTarget, currentDeltatime * rightRotationPointInfo.rotationPointSpeed);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (currentLeftWeaponRotationPoint != null) {
|
|||
|
|
if (followFullRotationPointDirection) {
|
|||
|
|
updateFullRotationPoint (weaponRotationPointToFollow, currentLeftWeaponRotationPoint,
|
|||
|
|
leftRotationPointInfo.rotationPointSpeed, currentDeltatime);
|
|||
|
|
} else {
|
|||
|
|
if (currentRotation > 180) {
|
|||
|
|
rotationXValue = (360 - currentRotation) / leftRotationPointInfo.rotationUpPointAmountMultiplier;
|
|||
|
|
|
|||
|
|
if (leftRotationPointInfo.useRotationUpClamp) {
|
|||
|
|
rotationXValue = Mathf.Clamp (rotationXValue, 0, leftRotationPointInfo.rotationUpClampAmount);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rotationXValue *= (-1) * currentLeftRotationDirection;
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
rotationXValue = currentRotation / leftRotationPointInfo.rotationDownPointAmountMultiplier;
|
|||
|
|
|
|||
|
|
if (leftRotationPointInfo.useRotationDownClamp) {
|
|||
|
|
rotationXValue = Mathf.Clamp (rotationXValue, 0, leftRotationPointInfo.rotationDownClamp);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rotationXValue *= currentLeftRotationDirection;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Quaternion weaponRotationPointTarget = Quaternion.Euler (new Vector3 (rotationXValue, 0, 0));
|
|||
|
|
|
|||
|
|
currentLeftWeaponRotationPoint.localRotation =
|
|||
|
|
Quaternion.Lerp (currentLeftWeaponRotationPoint.localRotation, weaponRotationPointTarget, currentDeltatime * leftRotationPointInfo.rotationPointSpeed);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
if (followFullRotationPointDirection) {
|
|||
|
|
updateFullRotationPoint (weaponRotationPointToFollow, currentWeaponRotationPoint,
|
|||
|
|
rotationPointInfo.rotationPointSpeed, currentDeltatime);
|
|||
|
|
} else {
|
|||
|
|
if (currentRotation > 180) {
|
|||
|
|
rotationXValue = (360 - currentRotation) / rotationPointInfo.rotationUpPointAmountMultiplier;
|
|||
|
|
|
|||
|
|
if (rotationPointInfo.useRotationUpClamp) {
|
|||
|
|
rotationXValue = Mathf.Clamp (rotationXValue, 0, rotationPointInfo.rotationUpClampAmount);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rotationXValue *= (-1) * currentRotationDirection;
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
rotationXValue = currentRotation / rotationPointInfo.rotationDownPointAmountMultiplier;
|
|||
|
|
|
|||
|
|
if (rotationPointInfo.useRotationDownClamp) {
|
|||
|
|
rotationXValue = Mathf.Clamp (rotationXValue, 0, rotationPointInfo.rotationDownClamp);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
rotationXValue *= currentRotationDirection;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Quaternion weaponRotationPointTarget = Quaternion.Euler (new Vector3 (rotationXValue, 0, 0));
|
|||
|
|
|
|||
|
|
currentWeaponRotationPoint.localRotation =
|
|||
|
|
Quaternion.Lerp (currentWeaponRotationPoint.localRotation, weaponRotationPointTarget, currentDeltatime * rotationPointInfo.rotationPointSpeed);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
if (usingDualWeapon) {
|
|||
|
|
|
|||
|
|
bool rightWeaponIsReset = false;
|
|||
|
|
bool leftWeaponIsReset = false;
|
|||
|
|
|
|||
|
|
if (currentRightWeaponRotationPoint != null) {
|
|||
|
|
if (currentRightWeaponRotationPoint.localRotation != Quaternion.identity) {
|
|||
|
|
currentRightWeaponRotationPoint.localRotation =
|
|||
|
|
Quaternion.Lerp (currentRightWeaponRotationPoint.localRotation, Quaternion.identity, currentDeltatime * rightRotationPointInfo.rotationPointSpeed);
|
|||
|
|
} else {
|
|||
|
|
rightWeaponIsReset = true;
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
rightWeaponIsReset = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (currentLeftWeaponRotationPoint != null) {
|
|||
|
|
if (currentLeftWeaponRotationPoint.localRotation != Quaternion.identity) {
|
|||
|
|
currentLeftWeaponRotationPoint.localRotation =
|
|||
|
|
Quaternion.Lerp (currentLeftWeaponRotationPoint.localRotation, Quaternion.identity, currentDeltatime * leftRotationPointInfo.rotationPointSpeed);
|
|||
|
|
} else {
|
|||
|
|
leftWeaponIsReset = true;
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
leftWeaponIsReset = true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (rightWeaponIsReset && leftWeaponIsReset) {
|
|||
|
|
usingWeaponRotationPoint = false;
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
if (currentWeaponRotationPoint != null) {
|
|||
|
|
if (currentWeaponRotationPoint.localRotation != Quaternion.identity) {
|
|||
|
|
|
|||
|
|
currentWeaponRotationPoint.localRotation =
|
|||
|
|
Quaternion.Lerp (currentWeaponRotationPoint.localRotation, Quaternion.identity, currentDeltatime * rotationPointInfo.rotationPointSpeed);
|
|||
|
|
} else {
|
|||
|
|
usingWeaponRotationPoint = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void updateFullRotationPoint (Transform rotationPointToFollow, Transform currentRotationPoint, float rotationPointSpeed, float currentDeltatime)
|
|||
|
|
{
|
|||
|
|
Quaternion weaponRotationPointTarget = Quaternion.LookRotation (rotationPointToFollow.forward, rotationPointToFollow.up);
|
|||
|
|
|
|||
|
|
Quaternion localRotation = Quaternion.Inverse (currentRotationPoint.parent.rotation) * weaponRotationPointTarget;
|
|||
|
|
|
|||
|
|
Vector3 localRotationEuler = localRotation.eulerAngles;
|
|||
|
|
|
|||
|
|
if (useFollowFullRotationClamp) {
|
|||
|
|
float rotationClampX = localRotationEuler.x;
|
|||
|
|
|
|||
|
|
if (rotationClampX > 180) {
|
|||
|
|
rotationClampX = (360 - rotationClampX) / followFullRotationPointMultipliers.x;
|
|||
|
|
|
|||
|
|
rotationClampX = Mathf.Clamp (rotationClampX, 0, followFullRotationClampX.x);
|
|||
|
|
|
|||
|
|
rotationClampX *= (-1) * currentRotationDirection;
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
rotationClampX = rotationClampX / followFullRotationPointMultipliers.x;
|
|||
|
|
|
|||
|
|
rotationClampX = Mathf.Clamp (rotationClampX, 0, followFullRotationClampX.y);
|
|||
|
|
|
|||
|
|
rotationClampX *= currentRotationDirection;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
float rotationClampY = localRotationEuler.y;
|
|||
|
|
|
|||
|
|
if (rotationClampY > 180) {
|
|||
|
|
rotationClampY = (360 - rotationClampY) / followFullRotationPointMultipliers.y;
|
|||
|
|
|
|||
|
|
rotationClampY = Mathf.Clamp (rotationClampY, 0, followFullRotationClampY.x);
|
|||
|
|
|
|||
|
|
rotationClampY *= (-1) * currentRotationDirection;
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
rotationClampY = rotationClampY / followFullRotationPointMultipliers.y;
|
|||
|
|
|
|||
|
|
rotationClampY = Mathf.Clamp (rotationClampY, 0, followFullRotationClampY.y);
|
|||
|
|
|
|||
|
|
rotationClampY *= currentRotationDirection;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
float rotationClampZ = localRotationEuler.z;
|
|||
|
|
|
|||
|
|
if (rotationClampZ > 180) {
|
|||
|
|
rotationClampZ = (360 - rotationClampZ) / followFullRotationPointMultipliers.z;
|
|||
|
|
|
|||
|
|
rotationClampZ = Mathf.Clamp (rotationClampZ, 0, followFullRotationClampZ.x);
|
|||
|
|
|
|||
|
|
rotationClampZ *= (-1) * currentRotationDirection;
|
|||
|
|
|
|||
|
|
} else {
|
|||
|
|
rotationClampZ = rotationClampZ / followFullRotationPointMultipliers.z;
|
|||
|
|
|
|||
|
|
rotationClampZ = Mathf.Clamp (rotationClampZ, 0, followFullRotationClampZ.y);
|
|||
|
|
|
|||
|
|
rotationClampZ *= currentRotationDirection;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
localRotationEuler = new Vector3 (rotationClampX, rotationClampY, rotationClampZ);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
localRotation = Quaternion.Euler (localRotationEuler);
|
|||
|
|
|
|||
|
|
if (useSmoothRotationPointValue) {
|
|||
|
|
currentRotationPoint.localRotation =
|
|||
|
|
Quaternion.Lerp (currentRotationPoint.localRotation, localRotation, smoothRotationPointValue);
|
|||
|
|
} else {
|
|||
|
|
currentRotationPoint.localRotation =
|
|||
|
|
Quaternion.Lerp (currentRotationPoint.localRotation, localRotation, currentTime * rotationPointSpeed);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// The angle between dirA and dirB around axis
|
|||
|
|
public static float AngleAroundAxis (Vector3 dirA, Vector3 dirB, Vector3 axis)
|
|||
|
|
{
|
|||
|
|
// Project A and B onto the plane orthogonal target axis
|
|||
|
|
dirA = dirA - Vector3.Project (dirA, axis);
|
|||
|
|
dirB = dirB - Vector3.Project (dirB, axis);
|
|||
|
|
|
|||
|
|
// Find (positive) angle between A and B
|
|||
|
|
float angle = Vector3.Angle (dirA, dirB);
|
|||
|
|
return angle * (Vector3.Dot (axis, Vector3.Cross (dirA, dirB)) < 0 ? -1 : 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setCurrentBodyRotation (float bodyRotation)
|
|||
|
|
{
|
|||
|
|
currentExtraRotation = bodyRotation;
|
|||
|
|
auxCurrentExtraRotation = currentExtraRotation;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void enableOrDisableIKUpperBody (bool value)
|
|||
|
|
{
|
|||
|
|
if (value) {
|
|||
|
|
IKUpperBodyActive = value;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
checkSetExtraRotationCoroutine (value);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void checkSetExtraRotationCoroutine (bool state)
|
|||
|
|
{
|
|||
|
|
if (changeExtraRotation != null) {
|
|||
|
|
StopCoroutine (changeExtraRotation);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (gameObject.activeInHierarchy) {
|
|||
|
|
changeExtraRotation = StartCoroutine (setExtraRotation (state));
|
|||
|
|
} else {
|
|||
|
|
if (state) {
|
|||
|
|
maxBendingAngle = originalAngleDifference;
|
|||
|
|
} else {
|
|||
|
|
maxBendingAngle = 0;
|
|||
|
|
|
|||
|
|
IKUpperBodyActive = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
IEnumerator setExtraRotation (bool state)
|
|||
|
|
{
|
|||
|
|
for (float t = 0; t < 1;) {
|
|||
|
|
t += Time.deltaTime * rotationSpeed;
|
|||
|
|
|
|||
|
|
if (state) {
|
|||
|
|
maxBendingAngle = Mathf.Lerp (maxBendingAngle, originalAngleDifference, t);
|
|||
|
|
} else {
|
|||
|
|
maxBendingAngle = Mathf.Lerp (maxBendingAngle, 0, t);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
yield return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!state) {
|
|||
|
|
IKUpperBodyActive = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public bool isIKUpperBodyActive ()
|
|||
|
|
{
|
|||
|
|
return IKUpperBodyActive;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void checkShakeUpperBodyRotationCoroutine (float extraAngleValue, float speedValue)
|
|||
|
|
{
|
|||
|
|
if (!shakeUpperBodyEnabled || !IKUpperBodyActive) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
stopShakeUpperBodyRotation ();
|
|||
|
|
|
|||
|
|
shakeUpperBodyRotationCoroutine = StartCoroutine (shakeUpperBodyRotation (extraAngleValue, speedValue));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void stopShakeUpperBodyRotation ()
|
|||
|
|
{
|
|||
|
|
if (shakeUpperBodyRotationCoroutine != null) {
|
|||
|
|
StopCoroutine (shakeUpperBodyRotationCoroutine);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
IEnumerator shakeUpperBodyRotation (float extraAngleValue, float speedValue)
|
|||
|
|
{
|
|||
|
|
float angleTarget = auxCurrentExtraRotation + extraAngleValue;
|
|||
|
|
|
|||
|
|
for (float t = 0; t < 1;) {
|
|||
|
|
t += Time.deltaTime * speedValue;
|
|||
|
|
|
|||
|
|
currentExtraRotation = Mathf.Lerp (currentExtraRotation, angleTarget, t);
|
|||
|
|
|
|||
|
|
yield return null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for (float t = 0; t < 1;) {
|
|||
|
|
t += Time.deltaTime * speedValue;
|
|||
|
|
|
|||
|
|
currentExtraRotation = Mathf.Lerp (currentExtraRotation, auxCurrentExtraRotation, t);
|
|||
|
|
|
|||
|
|
yield return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setCurrentWeaponRotationPoint (Transform newWeaponRotationPoint, weaponRotationPointInfo newRotationPointInfo, int newRotationDirection)
|
|||
|
|
{
|
|||
|
|
currentWeaponRotationPoint = newWeaponRotationPoint;
|
|||
|
|
|
|||
|
|
rotationPointInfo = newRotationPointInfo;
|
|||
|
|
|
|||
|
|
currentRotationDirection = newRotationDirection;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setUsingWeaponRotationPointState (bool state)
|
|||
|
|
{
|
|||
|
|
usingWeaponRotationPoint = state;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setUsingDualWeaponState (bool state)
|
|||
|
|
{
|
|||
|
|
usingDualWeapon = state;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setCurrentRightWeaponRotationPoint (Transform newWeaponRotationPoint, weaponRotationPointInfo newRotationPointInfo, int newRotationDirection)
|
|||
|
|
{
|
|||
|
|
currentRightWeaponRotationPoint = newWeaponRotationPoint;
|
|||
|
|
|
|||
|
|
rightRotationPointInfo = newRotationPointInfo;
|
|||
|
|
|
|||
|
|
currentRightRotationDirection = newRotationDirection;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setCurrentLeftWeaponRotationPoint (Transform newWeaponRotationPoint, weaponRotationPointInfo newRotationPointInfo, int newRotationDirection)
|
|||
|
|
{
|
|||
|
|
currentLeftWeaponRotationPoint = newWeaponRotationPoint;
|
|||
|
|
|
|||
|
|
leftRotationPointInfo = newRotationPointInfo;
|
|||
|
|
|
|||
|
|
currentLeftRotationDirection = newRotationDirection;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setTemporalObjectToFollow (Transform newObject)
|
|||
|
|
{
|
|||
|
|
temporalObjectToFollow = newObject;
|
|||
|
|
|
|||
|
|
usingTemporalObjectToFollow = temporalObjectToFollow != null;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setHorizontalBendingMultiplierValue (float newValue)
|
|||
|
|
{
|
|||
|
|
horizontalBendingMultiplier = newValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setOriginalHorizontalBendingMultiplier ()
|
|||
|
|
{
|
|||
|
|
setHorizontalBendingMultiplierValue (originalHorizontalBendingMultiplier);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setVerticalBendingMultiplierValue (float newValue)
|
|||
|
|
{
|
|||
|
|
verticalBendingMultiplier = newValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setOriginalVerticalBendingMultiplier ()
|
|||
|
|
{
|
|||
|
|
setVerticalBendingMultiplierValue (originalVerticalBendingMultiplier);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setFollowFullRotationPointDirectionState (bool state)
|
|||
|
|
{
|
|||
|
|
followFullRotationPointDirection = state;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setUseFollowFullRotationClampState (bool state)
|
|||
|
|
{
|
|||
|
|
useFollowFullRotationClamp = state;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setNewFollowFullRotationClampX (Vector2 newFollowFullRotationClampXValues)
|
|||
|
|
{
|
|||
|
|
followFullRotationClampX = newFollowFullRotationClampXValues;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setNewFollowFullRotationClampY (Vector2 newFollowFullRotationClampYValues)
|
|||
|
|
{
|
|||
|
|
followFullRotationClampY = newFollowFullRotationClampYValues;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setNewFollowFullRotationClampZ (Vector2 newFollowFullRotationClampZValues)
|
|||
|
|
{
|
|||
|
|
followFullRotationClampZ = newFollowFullRotationClampZValues;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setExtraHorizontalRotationEnabledState (bool state)
|
|||
|
|
{
|
|||
|
|
extraHorizontalRotationEnabled = state;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setHorizontalMaxAngleDifference (float newValue)
|
|||
|
|
{
|
|||
|
|
horizontalMaxAngleDifference = newValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setVerticalMaxAngleDifference (float newValue)
|
|||
|
|
{
|
|||
|
|
verticalMaxAngleDifference = newValue;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setOriginalHorizontalMaxAngleDifference ()
|
|||
|
|
{
|
|||
|
|
setHorizontalMaxAngleDifference (originalHorizontalMaxAngleDifference);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setOriginalVerticalMaxAngleDifference ()
|
|||
|
|
{
|
|||
|
|
setVerticalMaxAngleDifference (originalVerticalMaxAngleDifference);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setFullBodyAwarenessActiveState (bool state)
|
|||
|
|
{
|
|||
|
|
fullBodyAwarenessActive = state;
|
|||
|
|
|
|||
|
|
if (fullBodyAwarenessActive) {
|
|||
|
|
if (currentWeaponRotationPoint != null) {
|
|||
|
|
currentWeaponRotationPoint.localRotation = Quaternion.identity;
|
|||
|
|
|
|||
|
|
usingWeaponRotationPoint = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
//EDITOR FUNCTIONS
|
|||
|
|
public void setNewChestUpVectorValue (Vector3 newValue)
|
|||
|
|
{
|
|||
|
|
chestUpVector = newValue;
|
|||
|
|
|
|||
|
|
updateComponent ();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setSpineTransform (Transform newTransform)
|
|||
|
|
{
|
|||
|
|
spineTransform = newTransform;
|
|||
|
|
|
|||
|
|
updateComponent ();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void setChestTransform (Transform newTransform)
|
|||
|
|
{
|
|||
|
|
chestTransform = newTransform;
|
|||
|
|
|
|||
|
|
updateComponent ();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
public void updateComponent ()
|
|||
|
|
{
|
|||
|
|
GKC_Utils.updateComponent (this);
|
|||
|
|
|
|||
|
|
GKC_Utils.updateDirtyScene ("Update Upper Body Rotation System", gameObject);
|
|||
|
|
}
|
|||
|
|
}
|