536 lines
13 KiB
C#
536 lines
13 KiB
C#
/***********************************************
|
|
EasyTouch Controls
|
|
Copyright © 2016 The Hedgehog Team
|
|
http://www.thehedgehogteam.com/Forum/
|
|
|
|
The.Hedgehog.Team@gmail.com
|
|
|
|
**********************************************/
|
|
using UnityEngine;
|
|
using System.Collections;
|
|
|
|
[System.Serializable]
|
|
public class ETCAxis {
|
|
|
|
#region Enumeration
|
|
public enum DirectAction {Rotate, RotateLocal,Translate, TranslateLocal, Scale, Force,RelativeForce, Torque,RelativeTorque, Jump};
|
|
public enum AxisInfluenced{X,Y,Z};
|
|
public enum AxisValueMethod {Classical, Curve};
|
|
public enum AxisState {None,Down,Press,Up, DownUp,DownDown,DownLeft,DownRight, PressUp, PressDown, PressLeft, PressRight};
|
|
public enum ActionOn {Down,Press};
|
|
#endregion
|
|
|
|
#region Members
|
|
public string name;
|
|
|
|
public bool autoLinkTagPlayer = false;
|
|
public string autoTag ="Player";
|
|
public GameObject player;
|
|
|
|
public bool enable;
|
|
public bool invertedAxis;
|
|
public float speed;
|
|
|
|
//
|
|
public float deadValue;
|
|
public AxisValueMethod valueMethod;
|
|
public AnimationCurve curveValue;
|
|
|
|
public bool isEnertia;
|
|
public float inertia;
|
|
public float inertiaThreshold;
|
|
|
|
// Auto stabilization
|
|
public bool isAutoStab;
|
|
public float autoStabThreshold;
|
|
public float autoStabSpeed;
|
|
private float startAngle;
|
|
|
|
// Clamp rotation
|
|
public bool isClampRotation;
|
|
public float maxAngle;
|
|
public float minAngle;
|
|
|
|
// time push
|
|
public bool isValueOverTime;
|
|
public float overTimeStep;
|
|
public float maxOverTimeValue;
|
|
|
|
// AvisValue
|
|
public float axisValue;
|
|
public float axisSpeedValue;
|
|
public float axisThreshold;
|
|
public bool isLockinJump=false;
|
|
private Vector3 lastMove;
|
|
|
|
public AxisState axisState;
|
|
|
|
[SerializeField]
|
|
private Transform _directTransform;
|
|
public Transform directTransform {
|
|
get {
|
|
return _directTransform;
|
|
}
|
|
|
|
set {
|
|
_directTransform = value;
|
|
if (_directTransform!=null){
|
|
directCharacterController = _directTransform.GetComponent<CharacterController>();
|
|
directRigidBody = _directTransform.GetComponent<Rigidbody>();
|
|
|
|
}
|
|
else{
|
|
directCharacterController=null;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public DirectAction directAction;
|
|
public AxisInfluenced axisInfluenced;
|
|
public ActionOn actionOn;
|
|
|
|
public CharacterController directCharacterController;
|
|
public Rigidbody directRigidBody;
|
|
|
|
public float gravity;
|
|
public float currentGravity=0;
|
|
public bool isJump = false;
|
|
|
|
// Simulation
|
|
public string unityAxis;
|
|
|
|
public bool showGeneralInspector=false;
|
|
public bool showDirectInspector=false;
|
|
public bool showInertiaInspector=false;
|
|
public bool showSimulatinInspector=false;
|
|
#endregion
|
|
|
|
#region Constructeur
|
|
public ETCAxis(string axisName){
|
|
name = axisName;
|
|
enable = true;
|
|
speed = 15;
|
|
invertedAxis = false;
|
|
isEnertia = false;
|
|
inertia = 0;
|
|
inertiaThreshold = 0.08f;
|
|
axisValue = 0;
|
|
axisSpeedValue = 0;
|
|
gravity = 0;
|
|
isAutoStab = false;
|
|
autoStabThreshold = 0.01f;
|
|
autoStabSpeed = 10;
|
|
maxAngle = 90;
|
|
minAngle = 90;
|
|
axisState = AxisState.None;
|
|
maxOverTimeValue = 1;
|
|
overTimeStep = 1;
|
|
isValueOverTime = false;
|
|
axisThreshold = 0.5f;
|
|
deadValue = 0.1f;
|
|
actionOn = ActionOn.Press;
|
|
}
|
|
#endregion
|
|
|
|
#region Public method
|
|
public void InitAxis(){
|
|
|
|
if (autoLinkTagPlayer){
|
|
|
|
player = GameObject.FindGameObjectWithTag(autoTag);
|
|
if (player){
|
|
directTransform = player.transform;
|
|
}
|
|
}
|
|
startAngle = GetAngle();
|
|
}
|
|
|
|
public void UpdateAxis(float realValue, bool isOnDrag, ETCBase.ControlType type,bool deltaTime=true){
|
|
|
|
// Auto link
|
|
if (autoLinkTagPlayer && player==null || ( player && !player.activeSelf)){
|
|
player = GameObject.FindGameObjectWithTag(autoTag);
|
|
if (player){
|
|
directTransform = player.transform;
|
|
}
|
|
}
|
|
|
|
|
|
// Auto stabilization
|
|
if (isAutoStab && axisValue ==0 && _directTransform){
|
|
DoAutoStabilisation();
|
|
}
|
|
|
|
if (invertedAxis){realValue *= -1;}
|
|
|
|
// Time push
|
|
if (isValueOverTime && realValue!=0){
|
|
|
|
axisValue += overTimeStep * Mathf.Sign(realValue ) * Time.deltaTime;
|
|
|
|
if (Mathf.Sign(axisValue )>0){
|
|
axisValue = Mathf.Clamp( axisValue,0,maxOverTimeValue);
|
|
}
|
|
else{
|
|
axisValue = Mathf.Clamp( axisValue,-maxOverTimeValue,0);
|
|
}
|
|
}
|
|
|
|
// Axis value
|
|
ComputAxisValue(realValue, type,isOnDrag,deltaTime );
|
|
|
|
}
|
|
|
|
public void UpdateButton(){
|
|
|
|
// Auto link
|
|
if (autoLinkTagPlayer && player==null || ( player && !player.activeSelf)){
|
|
player = GameObject.FindGameObjectWithTag(autoTag);
|
|
if (player){
|
|
directTransform = player.transform;
|
|
}
|
|
}
|
|
|
|
if (isValueOverTime){
|
|
axisValue += overTimeStep * Time.deltaTime;
|
|
axisValue = Mathf.Clamp( axisValue,0,maxOverTimeValue);
|
|
}
|
|
else{
|
|
if (axisState == AxisState.Press || axisState == AxisState.Down){
|
|
axisValue = 1;
|
|
}
|
|
else{
|
|
axisValue = 0;
|
|
}
|
|
}
|
|
|
|
switch (actionOn){
|
|
case ActionOn.Down:
|
|
axisSpeedValue = axisValue * speed ;
|
|
if (axisState == AxisState.Down){
|
|
DoDirectAction();
|
|
}
|
|
break;
|
|
case ActionOn.Press:
|
|
axisSpeedValue = axisValue * speed * Time.deltaTime;
|
|
if (axisState == AxisState.Press){
|
|
DoDirectAction();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
public void ResetAxis(){
|
|
if (!isEnertia || (isEnertia && Mathf.Abs(axisValue)<inertiaThreshold) ){
|
|
axisValue =0;
|
|
axisSpeedValue =0;
|
|
}
|
|
}
|
|
|
|
public void DoDirectAction(){
|
|
|
|
if (directTransform){
|
|
Vector3 localAxis = GetInfluencedAxis();
|
|
|
|
switch ( directAction){
|
|
case ETCAxis.DirectAction.Rotate:
|
|
directTransform.Rotate( localAxis * axisSpeedValue, Space.World);
|
|
break;
|
|
|
|
case ETCAxis.DirectAction.RotateLocal:
|
|
directTransform.Rotate( localAxis * axisSpeedValue,Space.Self);
|
|
break;
|
|
|
|
|
|
case ETCAxis.DirectAction.Translate:
|
|
if ( directCharacterController==null){
|
|
|
|
directTransform.Translate(localAxis * axisSpeedValue,Space.World);
|
|
}
|
|
else{
|
|
if (directCharacterController.isGrounded || !isLockinJump){
|
|
Vector3 direction = localAxis * axisSpeedValue;
|
|
directCharacterController.Move( direction );
|
|
lastMove = localAxis * (axisSpeedValue/Time.deltaTime);
|
|
}
|
|
else{
|
|
directCharacterController.Move( lastMove * Time.deltaTime);
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case ETCAxis.DirectAction.TranslateLocal:
|
|
if ( directCharacterController==null){
|
|
directTransform.Translate(localAxis * axisSpeedValue,Space.Self);
|
|
}
|
|
else{
|
|
if (directCharacterController.isGrounded || !isLockinJump){
|
|
Vector3 direction = directCharacterController.transform.TransformDirection(localAxis) * axisSpeedValue;
|
|
directCharacterController.Move( direction );
|
|
lastMove =directCharacterController.transform.TransformDirection(localAxis) * (axisSpeedValue/Time.deltaTime);
|
|
}
|
|
else{
|
|
directCharacterController.Move( lastMove * Time.deltaTime );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case ETCAxis.DirectAction.Scale:
|
|
directTransform.localScale += localAxis * axisSpeedValue;
|
|
break;
|
|
|
|
case ETCAxis.DirectAction.Force:
|
|
if (directRigidBody!=null){
|
|
directRigidBody.AddForce( localAxis * axisValue * speed);
|
|
}
|
|
else{
|
|
Debug.LogWarning("ETCAxis : "+ name + " No rigidbody on gameobject : "+ _directTransform.name);
|
|
}
|
|
break;
|
|
|
|
case ETCAxis.DirectAction.RelativeForce:
|
|
if (directRigidBody!=null){
|
|
directRigidBody.AddRelativeForce( localAxis * axisValue * speed);
|
|
}
|
|
else{
|
|
Debug.LogWarning("ETCAxis : "+ name + " No rigidbody on gameobject : "+ _directTransform.name);
|
|
}
|
|
break;
|
|
|
|
case ETCAxis.DirectAction.Torque:
|
|
if (directRigidBody!=null){
|
|
directRigidBody.AddTorque(localAxis * axisValue * speed);
|
|
}
|
|
else{
|
|
Debug.LogWarning("ETCAxis : "+ name + " No rigidbody on gameobject : "+ _directTransform.name);
|
|
}
|
|
break;
|
|
|
|
case ETCAxis.DirectAction.RelativeTorque:
|
|
if (directRigidBody!=null){
|
|
directRigidBody.AddRelativeTorque(localAxis * axisValue * speed);
|
|
}
|
|
else{
|
|
Debug.LogWarning("ETCAxis : "+ name + " No rigidbody on gameobject : "+ _directTransform.name);
|
|
}
|
|
break;
|
|
|
|
case ETCAxis.DirectAction.Jump:
|
|
if ( directCharacterController!=null){
|
|
|
|
if (!isJump){
|
|
isJump = true;
|
|
currentGravity = speed;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (isClampRotation && directAction == DirectAction.RotateLocal){
|
|
DoAngleLimitation();
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public void DoGravity(){
|
|
|
|
if (directCharacterController != null && gravity!=0){
|
|
|
|
if (!isJump){
|
|
Vector3 move = new Vector3(0,-gravity,0);
|
|
directCharacterController.Move( move * Time.deltaTime);
|
|
}
|
|
else{
|
|
currentGravity -= gravity*Time.deltaTime;
|
|
Vector3 move = new Vector3(0,currentGravity,0);
|
|
directCharacterController.Move( move * Time.deltaTime);
|
|
}
|
|
|
|
if (directCharacterController.isGrounded){
|
|
isJump = false;
|
|
currentGravity =0;
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Private methods
|
|
|
|
private void ComputAxisValue(float realValue, ETCBase.ControlType type, bool isOnDrag, bool deltaTime){
|
|
|
|
if (enable){
|
|
|
|
if (type == ETCBase.ControlType.Joystick){
|
|
|
|
if (valueMethod == AxisValueMethod.Classical){
|
|
float dist = Mathf.Max(Mathf.Abs(realValue),0.001f);
|
|
float dead = Mathf.Max(dist - deadValue, 0)/(1f - deadValue)/dist;
|
|
realValue *= dead;
|
|
|
|
}
|
|
else{
|
|
//realValue = deadCurve.Evaluate( Mathf.Abs(realValue)) * Mathf.Sign( realValue);
|
|
realValue = curveValue.Evaluate( realValue);
|
|
}
|
|
}
|
|
|
|
if (isEnertia){
|
|
realValue = (realValue-axisValue);
|
|
realValue /= inertia;
|
|
|
|
axisValue += realValue;
|
|
|
|
if (Mathf.Abs(axisValue)< inertiaThreshold && !isOnDrag ) {
|
|
axisValue = 0;
|
|
}
|
|
}
|
|
else if (!isValueOverTime || (isValueOverTime && realValue ==0)){
|
|
axisValue = realValue;
|
|
}
|
|
|
|
if (deltaTime){
|
|
axisSpeedValue = axisValue * speed * Time.deltaTime;
|
|
}
|
|
else{
|
|
axisSpeedValue = axisValue * speed;
|
|
}
|
|
}
|
|
else{
|
|
axisValue = 0;
|
|
axisSpeedValue =0;
|
|
}
|
|
}
|
|
|
|
private Vector3 GetInfluencedAxis(){
|
|
|
|
Vector3 axis = Vector3.zero;
|
|
|
|
switch(axisInfluenced){
|
|
case ETCAxis.AxisInfluenced.X:
|
|
axis = Vector3.right;
|
|
break;
|
|
case ETCAxis.AxisInfluenced.Y:
|
|
axis = Vector3.up;
|
|
break;
|
|
case ETCAxis.AxisInfluenced.Z:
|
|
axis = Vector3.forward;
|
|
break;
|
|
}
|
|
|
|
return axis;
|
|
}
|
|
|
|
private float GetAngle(){
|
|
|
|
float angle=0;
|
|
|
|
if (_directTransform!=null){
|
|
switch(axisInfluenced){
|
|
case AxisInfluenced.X:
|
|
angle = _directTransform.localRotation.eulerAngles.x;
|
|
break;
|
|
case AxisInfluenced.Y:
|
|
angle = _directTransform.localRotation.eulerAngles.y;
|
|
break;
|
|
case AxisInfluenced.Z:
|
|
angle = _directTransform.localRotation.eulerAngles.z;
|
|
break;
|
|
}
|
|
|
|
if (angle<=360 && angle>=180){
|
|
angle = angle -360;
|
|
}
|
|
}
|
|
|
|
return angle;
|
|
}
|
|
|
|
private void DoAutoStabilisation(){
|
|
|
|
float angle= GetAngle();
|
|
|
|
if (angle<=360 && angle>=180){
|
|
angle = angle -360;
|
|
}
|
|
|
|
if (angle > startAngle - autoStabThreshold || angle < startAngle + autoStabThreshold){
|
|
|
|
float axis=0;
|
|
Vector3 stabAngle = Vector3.zero;
|
|
|
|
if (angle > startAngle - autoStabThreshold){
|
|
axis = angle + autoStabSpeed/100f*Mathf.Abs (angle-startAngle) * Time.deltaTime*-1;
|
|
}
|
|
|
|
|
|
if (angle < startAngle + autoStabThreshold){
|
|
axis = angle + autoStabSpeed/100f*Mathf.Abs (angle-startAngle) * Time.deltaTime;
|
|
}
|
|
|
|
switch(axisInfluenced){
|
|
case AxisInfluenced.X:
|
|
stabAngle = new Vector3(axis,_directTransform.localRotation.eulerAngles.y,_directTransform.localRotation.eulerAngles.z);
|
|
break;
|
|
case AxisInfluenced.Y:
|
|
stabAngle = new Vector3(_directTransform.localRotation.eulerAngles.x,axis,_directTransform.localRotation.eulerAngles.z);
|
|
break;
|
|
case AxisInfluenced.Z:
|
|
stabAngle = new Vector3(_directTransform.localRotation.eulerAngles.x,_directTransform.localRotation.eulerAngles.y,axis);
|
|
break;
|
|
}
|
|
|
|
_directTransform.localRotation = Quaternion.Euler( stabAngle);
|
|
}
|
|
}
|
|
|
|
private void DoAngleLimitation(){
|
|
|
|
Quaternion q = _directTransform.localRotation;
|
|
|
|
q.x /= q.w;
|
|
q.y /= q.w;
|
|
q.z /= q.w;
|
|
q.w = 1.0f;
|
|
|
|
float newAngle = 0;
|
|
|
|
switch(axisInfluenced){
|
|
case AxisInfluenced.X:
|
|
newAngle = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.x);
|
|
newAngle = Mathf.Clamp (newAngle, -minAngle, maxAngle);
|
|
q.x = Mathf.Tan (0.5f * Mathf.Deg2Rad * newAngle);
|
|
break;
|
|
case AxisInfluenced.Y:
|
|
newAngle = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.y);
|
|
newAngle = Mathf.Clamp (newAngle, -minAngle, maxAngle);
|
|
q.y = Mathf.Tan (0.5f * Mathf.Deg2Rad * newAngle);
|
|
break;
|
|
case AxisInfluenced.Z:
|
|
newAngle = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.z);
|
|
newAngle = Mathf.Clamp (newAngle, -minAngle, maxAngle);
|
|
q.z = Mathf.Tan (0.5f * Mathf.Deg2Rad * newAngle);
|
|
break;
|
|
}
|
|
|
|
|
|
|
|
_directTransform.localRotation = q;
|
|
|
|
}
|
|
#endregion
|
|
|
|
public void InitDeadCurve(){
|
|
|
|
curveValue = AnimationCurve.EaseInOut(0,0,1,1);
|
|
curveValue.postWrapMode = WrapMode.PingPong;
|
|
curveValue.preWrapMode = WrapMode.PingPong;
|
|
}
|
|
|
|
|
|
}
|