using System.Collections;---- 基类
using System.Collections.Generic;
using UnityEngine;
public abstract class IUserInput : MonoBehaviour
{
//父类
[Header("---------------按键返回的信息------------------")]
//上下移动
public float Dup;
//左右移动
public float Dright;
//移动的距离
public float Dmag;
//方向
public Vector3 Dvec;
//摄像机
public float Jup;
public float Jright;
[Header("---------------others------------------")]
//1.按压式sigle
//2.一次性触发single
//3.double trigger
//是否跑步
public bool run;
//按键开关
protected bool inputEnabled=true;
//垂直目标方向
protected float targetDup;
//水平目标方向
protected float targetDright;
//垂直方向上的速度
protected float velocityDup;
//水平方向上的速度
protected float velocityDright;
/// <summary>
/// 椭圆映射法
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
protected Vector2 SquareToCircle(Vector2 input)
{
//设一个二维向量
Vector2 output=Vector2.zero;
//将xy进行椭圆映射运算
output.x = input.x * Mathf.Sqrt(1 - (input.y * input.y) / 2.0f);
output.y = input.y * Mathf.Sqrt(1 - (input.x * input.x) / 2.0f);
return output;
}
}
using System;-----------按钮位移控制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerInPut : IUserInput
{
[Header("---------------设置按键------------------")]
public string keyUp;
public string keyDown;
public string keyRight;
public string keyLeft;
public string keyA;
public string keyB;
public string keyC;
public string keyD;
public string keyE;
public string keyF;
public string keyG;
public string keyJRight;
public string keyJUp;
public string keyJDown;
public string keyJLeft;
[Header("-----------鼠标设置----------")]
//锁定目标
public bool lockOn;
//鼠标转动速度
public float mouseSensitiivityX;
public float mouseSensitiivityY;
private void Update()
{
//鼠标旋转
if (Input.GetMouseButton(2))
{
Jup = Input.GetAxis("Mouse Y")*mouseSensitiivityY;
Jright = Input.GetAxis("Mouse X")*mouseSensitiivityX;
}
//键盘转
else
{
Jup = (Input.GetKey(keyJUp) ? 1.0f : 0) - (Input.GetKey(keyJDown) ? 1.0f : 0);
Jright = (Input.GetKey(keyJRight) ? 1.0f : 0) - (Input.GetKey(keyJLeft) ? 1.0f : 0);
}
//两个二目运算符相运算得到目标的值
targetDup = (Input.GetKey(keyUp) ? 1.0f : 0) - (Input.GetKey(keyDown) ? 1.0f : 0);
targetDright = (Input.GetKey(keyRight) ? 1.0f : 0) - (Input.GetKey(keyLeft) ? 1.0f : 0);
//平滑处理上下的移动
Dup = Mathf.SmoothDamp(Dup, targetDup, ref velocityDup, 0.1f);
//平滑处理左右移动
Dright = Mathf.SmoothDamp(Dright, targetDright, ref velocityDright, 0.1f);
//如果开关关闭
if (inputEnabled==false)
{
//将目标值全部归零
targetDup = 0;
targetDright = 0;
}
//将此二维向量传入椭圆映射方法中
Vector2 tempDAixs = SquareToCircle(new Vector2(Dright, Dup));
//得到两个新的长度
float Dright2 = tempDAixs.x;
float Dup2 = tempDAixs.y;
//移动的距离
Dmag = Mathf.Sqrt(Dright2 * Dright2+ Dup2 * Dup2);
//移动方向的判定
Dvec = Dright2 * transform.right + Dup2 * transform.forward;
//跑步开关
run = Input.GetKey(keyA);
//锁目标
lockOn = Input.GetKeyDown(keyE);
}
}
using System;----------人物动作控制
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(Rigidbody))]
public class ActorController : MonoBehaviour
{
//人物模型
public GameObject model;
//playerinput类
public PlayerInPut pi;
//行走速度
public float walkSpeed;
//跑步速度
public float runMultiplier;
//动画
private Animator _animator;
//移动的向量
private Vector3 planarVec;
//人物刚体
private Rigidbody rig;
//上跳乘数
public float jumpVelocity;
//翻滚乘数
public float rollVelocity;
//冲量向量
private Vector3 thrustVec;
//相机脚本
public CameraController camcon;
//锁死位移
private bool lockPlanar;
//是否能攻击
private bool canAttack;
//轨道方向
private bool trackDirction;
//刚体
public CapsuleCollider col;
[Header("----------摩擦材质------------")]
public PhysicMaterial frictionOne;
public PhysicMaterial frictionZero;
//第三段攻击动画位移
private Vector3 deltaPos;
private float lerpTarget;
private float lerpTarget1;
private void Awake()
{
_animator = model.GetComponent<Animator>();
pi = GetComponent<PlayerInPut>();
rig = GetComponent<Rigidbody>();
col = GetComponent<CapsuleCollider>();
}
private void Update()
{
//锁定目标
if (pi.lockOn)
{
camcon.LockOnLock();
}
//如果摄像机不在锁定状态
if (camcon.lockState==false)
{
//播放动画 里面用了一个线性插值运算
_animator.SetFloat("forward",
pi.Dmag*Mathf.Lerp(_animator.GetFloat("forward"),
pi.run ? 2.0f : 1.0f,0.5f));
_animator.SetFloat("right",0);
}
else
{
//如果摄像机在锁定状态
//世界转本地
Vector3 localDvec = transform.InverseTransformVector(pi.Dvec);
_animator.SetFloat("forward",localDvec.z*((pi.run) ? 2.0f : 1.0f));
_animator.SetFloat("right",localDvec.x *((pi.run) ? 2.0f : 1.0f));
}
//翻滚动画
if (rig.velocity.magnitude>1.0f)
{
_animator.SetTrigger("roll");
}
//跳跃
if (Input.GetKeyDown(pi.keyB))
{
_animator.SetTrigger("jump");
canAttack = false;
}
//举盾
_animator.SetBool("defense",Input.GetKey(pi.keyD)||Input.GetKey(pi.keyG));
if ((Input.GetKeyDown(pi.keyF)||Input.GetKeyDown(pi.keyC))&&CheckState("ground")&&canAttack)
{
_animator.SetTrigger("attack");
}
if (camcon.lockState==false)
{
//移动的向量大于0.1
if (pi.Dmag>0.1f)
{
//人物的朝向
model.transform.forward = Vector3.Slerp(model.transform.forward, pi.Dvec, 0.3f);
}
//如果平面没锁
if (lockPlanar==false)
{
//移动的方向向量
planarVec = pi.Dmag * model.transform.forward*walkSpeed*(pi.run?runMultiplier:1.0f);
}
}
else
{
//如果摄像机锁死
//没有轨道方向
if (trackDirction==false)
{
//角色和父物体同向
model.transform.forward = transform.forward;
}
else
{
//反之角色的向量和平面的方向一样
model.transform.forward = planarVec.normalized;
}
//如果平面没锁
if (lockPlanar==false)
{
//移动的方向向量
planarVec=pi.Dvec*walkSpeed*(pi.run?runMultiplier:1.0f);
}
}
}
private void FixedUpdate()
{
//位置加上第三段攻击的位置
rig.position += deltaPos;
//移动
//rig.position+=planarVec*Time.fixedDeltaTime+thrustVec;
rig.velocity=new Vector3(planarVec.x,rig.velocity.y,planarVec.z)+thrustVec;
//冲量归零
thrustVec=Vector3.zero;
deltaPos=Vector3.zero;
}
//检测当前播放的动画
private bool CheckState(string stateName, string layerName = "Base Layer")
{
return _animator.GetCurrentAnimatorStateInfo(_animator.GetLayerIndex(layerName)).IsName(stateName);
}
/// 信息传输
/// ↓
/// ↓
/// ↓
//进入跳跃状态的时候
public void OnJumpEnter()
{
//关闭pi
pi.enabled = false;
//锁死平面
lockPlanar = true;
//开始轨道向量
trackDirction = true;
//开始计算冲量
thrustVec=new Vector3(0,jumpVelocity,0);
}
//在地上的时候
public void IsGround()
{
//开启动画参数
_animator.SetBool("isGround",true);
//打开攻击
canAttack = true;
}
//不在地上的额时候
public void IsNotGround()
{
_animator.SetBool("isGround",false);
}
//进入站立状态
public void OnGroundEnter()
{
pi.enabled = true;
lockPlanar = false;
col.material = frictionOne;
trackDirction = false;
}
//离开站立状态
public void OnGroundExit()
{
col.material = frictionZero;
}
//进入落下状态
public void OnFallEnter()
{
pi.enabled = false;
lockPlanar = true;
}
//进入翻滚状态
public void OnRollEnter()
{
thrustVec=new Vector3(0,rollVelocity,0);
pi.enabled = false;
lockPlanar = true;
trackDirction = true;
}
//进入后跳状态
public void OnJabEnter()
{
pi.enabled = false;
lockPlanar = true;
}
//在后跳动画中
public void OnJabUpdate()
{
thrustVec = model.transform.forward*_animator.GetFloat("jabVelocity");
}
//在第一次攻击进入时
public void OnAttack1hAEnter()
{
pi.enabled = false;
//权重
lerpTarget = 1.0f;
}
//攻击转入站立动画时
public void OnAttackidleEnter()
{
pi.enabled = true;
lerpTarget = 0f;
}
//第一次攻击动画持续时
public void OnAttack1hAUpdate()
{
thrustVec = model.transform.forward*_animator.GetFloat("attack1hAVelocity");
float currentWeight = _animator.GetLayerWeight(_animator.GetLayerIndex("attack"));
currentWeight = Mathf.Lerp(currentWeight,lerpTarget,0.3f);
_animator.SetLayerWeight(_animator.GetLayerIndex("attack"),currentWeight);
}
//攻击转入站立动画中
public void OnAttackidleUpdate()
{
float currentWeight = _animator.GetLayerWeight(_animator.GetLayerIndex("attack"));
currentWeight = Mathf.Lerp(currentWeight,lerpTarget,0.3f);
_animator.SetLayerWeight(_animator.GetLayerIndex("attack"),currentWeight);
}
//在防御进入时
public void OnDefense1hEnter()
{
//pi.enabled = false;
//权重
lerpTarget1 = 1.0f;
}
//防御转入站立动画时
public void OnDefense1hidleEnter()
{
pi.enabled = true;
lerpTarget1 = 0f;
}
//防御动画持续时
public void OnDefense1hUpdate()
{
float currentWeight = _animator.GetLayerWeight(_animator.GetLayerIndex("defense"));
currentWeight = Mathf.Lerp(currentWeight,lerpTarget1,0.3f);
_animator.SetLayerWeight(_animator.GetLayerIndex("defense"),currentWeight);
}
//防御转入站立动画中
public void OnDefense1hidleUpdate()
{
float currentWeight = _animator.GetLayerWeight(_animator.GetLayerIndex("defense"));
currentWeight = Mathf.Lerp(currentWeight,lerpTarget1,0.3f);
_animator.SetLayerWeight(_animator.GetLayerIndex("defense"),currentWeight);
}
//第三次攻击动画持续时
public void Onattack1hCUpdate()
{
thrustVec = model.transform.up*_animator.GetFloat("attack1hC");
}
public void OnUpDateRM(object _deltaPos)
{
if (CheckState("attack1hC","attack"))
{
deltaPos+=(deltaPos = (Vector3) _deltaPos)/2.0f;
}
}
//退出
public void Quit()
{
Application.Quit();
}
}
using System;----------------相机控制-----------
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
public class CameraController : MonoBehaviour
{
//获取到人移动脚本
public PlayerInPut pi;
//镜头旋转速度
public float horizontalSpeed;
public float verticalSpeed;
//获取到两个物体
private GameObject palyerHandle;
private GameObject cameraHandle;
//竖直旋转中间角度
private float tempEulerx;
//人物模型
private GameObject model;
//摄像机
private GameObject _camera;
//相机内部速度
private Vector3 cameraDampVelocity;
//锁定的目标
[SerializeField]
private LockTraget lockTaeget;
//准心
public Image img;
//是否是锁定状态
public bool lockState;
private void Awake()
{
//获取到组件
cameraHandle = transform.parent.gameObject;
palyerHandle = cameraHandle.transform.parent.gameObject;
model = palyerHandle.GetComponent<ActorController>().model;
_camera = Camera.main.gameObject;
//初始角度
tempEulerx = 20;
img.enabled = false;
lockState = false;
//看不到鼠标
//Cursor.lockState = CursorLockMode.Locked;
}
private void FixedUpdate()
{
//如果没有锁定角度
if (lockTaeget==null)
{
//人物的欧拉角不受别的旋转影响而改变
Vector3 tempModelEuler = model.transform.eulerAngles;
//水平左右旋转跟人一起转
palyerHandle.transform.Rotate(Vector3.up,pi.Jright*horizontalSpeed*Time.fixedDeltaTime);
//竖直旋转
tempEulerx -= pi.Jup * verticalSpeed * Time.fixedDeltaTime;
//控制竖直旋转的范围
tempEulerx = Mathf.Clamp(tempEulerx, -40, 30);
//摄像机本地的旋转角度
cameraHandle.transform.localEulerAngles= new Vector3(tempEulerx, 0,0);
//转动方向的时候人物的方向不受改变
model.transform.eulerAngles = tempModelEuler;
}
else
{
//否则人物的朝向始终朝向目标
Vector3 tempForward = lockTaeget.obj.transform.position - model.transform.position;
//将他的y值和人物的y值定一样
tempForward.y = 0;
palyerHandle.transform.forward = tempForward;
//看脚底
cameraHandle.transform.LookAt(lockTaeget.obj.transform);
}
//摄像机跟随
_camera.transform.position=Vector3.SmoothDamp(_camera.transform.position,transform.position,ref cameraDampVelocity, 0.2f*Time.deltaTime);
//camera.transform.position = Vector3.Lerp(camera.transform.position,transform.position,0.2f);
//旋转
//_camera.transform.eulerAngles = transform.eulerAngles;
_camera.transform.LookAt(cameraHandle.transform);
}
//锁定目标
public void LockOnLock()
{
Vector3 modelorigin1 = model.transform.position;
Vector3 modelorigin2 = modelorigin1 + Vector3.up;
Vector3 boCenter = modelorigin2 + model.transform.forward * 5.0f;
//相交体检测
Collider[] cols = Physics.OverlapBox(boCenter, new Vector3(0.5f, 0.5f, 5f)
, model.transform.rotation, LayerMask.GetMask("Enemy"));
//没有检测到敌人
if (cols.Length==0)
{
Debug.Log("空的");
//关闭这些
lockTaeget = null;
img.enabled = false;
lockState = false;
}
else
{
//遍历这些检测到的东西
foreach (Collider item in cols)
{
//如果类不为空或者锁定的目标信息就是现在这个信息
if (lockTaeget!=null&&lockTaeget.obj==item.gameObject)
{
//关掉
lockTaeget = null;
img.enabled = false;
lockState = false;
break;
}
//获取到目标信息(半高)
lockTaeget =new LockTraget(item.gameObject,item.bounds.extents.y);
img.enabled = true;
lockState = true;
break;
}
}
}
private void Update()
{
//有目标
if (lockTaeget!=null)
{
//获取到图片的坐标
img.rectTransform.position = Camera.main.WorldToScreenPoint(lockTaeget.obj.transform.position +
new Vector3(0, lockTaeget.halfHeight, 0));
//判断距离
if (Vector3.Distance(model.transform.position,lockTaeget.obj.transform.position)>10.0f)
{
lockTaeget = null;
img.enabled = false;
lockState = false;
}
}
}
//目标类
private class LockTraget
{
public GameObject obj;
public float halfHeight;
public LockTraget(GameObject _obj,float _halfHeight)
{
obj = _obj;
halfHeight = _halfHeight;
}
}
}
using System.Collections;-----------清除动画信号
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Animations;
public class FsmClearSignels : StateMachineBehaviour
{
//清除进入前的数据
public string[] clearAtEnter;
public string[] clearAtExit;
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
foreach (var signal in clearAtEnter)
{
//清除
animator.ResetTrigger(signal);
}
}
// public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex, AnimatorControllerPlayable controller)
// {
// foreach (var singal in clearAtExit)
// {
// animator.ResetTrigger(singal);
// }
// }
}
using System.Collections;---------状态机开始前清除信号
using System.Collections.Generic;
using UnityEngine;
public class FsmOnEnter : StateMachineBehaviour
{
public string[] OnEnterMessages;
public override void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
foreach (var msg in OnEnterMessages)
{
//通知母组件给其信息
animator.gameObject.SendMessageUpwards(msg);
}
}
}
using System.Collections;---------状态机开始后清除信号
using System.Collections.Generic;
using UnityEngine;
public class FSMOnExit : StateMachineBehaviour
{
public string[] onExitMessages;
public override void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
foreach (var msg in onExitMessages)
{
animator.gameObject.SendMessageUpwards(msg);
}
}
}
using System.Collections;---------状态机进行中清除信号
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Animations;
public class FsmOnUpdate : StateMachineBehaviour
{
public string[] OnUpdataMessage;
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex,
AnimatorControllerPlayable controller)
{
foreach (var msg in OnUpdataMessage)
{
animator.SendMessageUpwards(msg);
}
}
}
using System;-----------左胳膊转动ik
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LeftArmAnimFix : MonoBehaviour
{
private Animator anim;
public Vector3 turna;
private void Awake()
{
anim = GetComponent<Animator>();
}
private void OnAnimatorIK(int layerIndex)
{
if (anim.GetBool("defense")==false)
{
Transform leftLowerArm = anim.GetBoneTransform(HumanBodyBones.LeftLowerArm);
leftLowerArm.localEulerAngles+=0.75f*turna;
anim.SetBoneLocalRotation(HumanBodyBones.LeftLowerArm,Quaternion.Euler(leftLowerArm.localEulerAngles));
}
}
}
using System;-------------------判断在不在地上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class OnGroundSenser : MonoBehaviour
{
//检测是否在地上
public CapsuleCollider capcol;
private Vector3 point1;
private Vector3 point2;
private float radius;
public float offset;
private void Awake()
{
radius = capcol.radius;
}
private void FixedUpdate()
{
point1 = transform.position + transform.up *(radius-offset);
point2 = transform.position + transform.up * (capcol.height-offset) - transform.up * radius;
Collider[] outputcols = Physics.OverlapCapsule(point1, point2, radius, 1 << 8);
if (outputcols.Length!=0)
{
SendMessageUpwards("IsGround");
}
else
{
SendMessageUpwards("IsNotGround");
}
}
}
using System;-----------动画事件
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TriggerController : MonoBehaviour
{
private Animator anim;
private void Awake()
{
anim = GetComponent<Animator>();
}
public void ResetTrigger(string triggerName)
{
anim.ResetTrigger(triggerName);
Debug.Log(triggerName);
}
}
|