using System.Collections; using System.Collections.Generic; using UnityEngine; using Spine; using Spine.Unity; using UnityEngine.LowLevel; using UnityEngine.Playables; using System.ComponentModel; using Unity.VisualScripting; using System; using Base.Common; using cfg; using static UnityEngine.EventSystems.EventTrigger; using UnityEngine.InputSystem; using TMPro; [Serializable] public struct AttackInfo { public int damage; public Vector3 attackDir; public float force; public bool changeHurt; public float repelValue; } public enum PlayerAttackState { Idle = 0, WalkForward = 1, WalkBack = 2, } public class PlayerController : MoveCharacter { [Header("玩家属性")] public int playerId; public bool canJump; public bool canfly; public bool endTranSummon; //是否在结束变身后召唤英灵 [Header("变身英灵")] public bool isUltimate; //英灵释放大招 public bool keyTransfigurateRelease; //松开英灵释放大招键 public List changePrefabs; public int[] needCorpses; private GameObject spiritObj; //当前变身的对象 public int endChange = 0; //结束变身后召唤的英灵 public Vector2 rightDir; [Header("玩家组件")] public UIHP uiMp; public PlayerRope playerRope; public EventTrigger eventTrigger; public SprintLinkTrigger sprintLinkTrigger; private Spirits spirits; public Collider soulCollector; public SkeletonMecanim skeletonMecanim; public SkeletonDataAsset[] playerSpine; private SpiritSystem spiritSystem; [Header("血量")] private int curHp; private int curTotalHp; [Header("蓝耗")] public float mp; public float totalMp; public float totalMp_2Players; //双人模式下总蓝量 public bool isMpRepel = true; public bool isRapedReply; public float mpReplySpeed; public float mpReplySpeed_2Players; //双人模式下蓝量回复速度 public float rapidReplySpeed; public float lostMp; private float addMp = 10; public GameObject soul; public GameObject rapidReplyEffect; [Header("移动属性")] public Vector2 moveVec; //玩家不动时移动数据 [HideInInspector] public Vector2 leftDir; [Header("冲刺属性")] public float rushSpeed = 100; public float rushCostMp = 5; public Vector3 rushDir; public float rushInvincibleTime = 0.2f; [HideInInspector] public float rushTime; public float totalRushTime = 0.5f; [HideInInspector] public float cacheRushTime; //无法Rush时按下Rush键不会Rush,手感不好,缓存几帧,在这几帧内落地会立即Rush; public float totalCacheRushTime = 0.1f; [Header("链条属性")] public float sprintCostMp = 5; [HideInInspector] public float cachePullRopeTime; public float totalCachePullRopeTime = 0.1f; [Header("跳跃属性")] public float jumpSpeed = 10; public float airJumpSpeed = 10; public int airJumped; public int airJumpNumber = 1; //最大跳跃次数 public float canAirJumpSpeed = 5;//y轴速度大于这个值时不能进行空中跳跃 [HideInInspector] public float canJumpTime; //离开平台后仍然可以跳跃的时间,用于提升手感 public float leaveGroundCanJumpTime = 0.1f; [HideInInspector] public float cacheJumpTime; //即将落地时按下跳跃键不会跳跃,手感不好,缓存几帧,在这几帧内落地会立即跳跃; public float totalCacheJumpTime = 0.1f; [Header("飞行属性")] public float flySpeed = 5; public float maxFlyHeight; [Header("召唤属性")] public float cacheDir; //召唤的时候按左右召唤结束不会响应手感不好,缓存一下,召唤后摇期间有左右响应的话会转向 [HideInInspector] public float summonTime; [HideInInspector] public float cacheSummonTime; //无法召唤时按下召唤键不会召唤,手感不好,缓存几帧,在这几帧内落地会立即召唤; [HideInInspector] public int cacheSummonId; [Header("召唤使魔")] public List demonicPrefabs; public List demonicSummonPos; public Dictionary> demonicDic; private List arrows = new List(); private List giants = new List(); private List swords = new List(); [Header("攻击")] public PlayerAttackState attackState; public float attackMoveSpeed = 5f; [HideInInspector] public float cacheAttackTime; //无法攻击时按下攻击键不会攻击,手感不好,缓存几帧,在这几帧内落地会立即攻击; public float totalCacheAttackTime = 0.1f; [Header("复活")] public float reviveTime; //复活时间 public float totalReviveTime; [Header("玩家是否在基地")] public bool isBaseBtnOut = false; [Header("八卦")] public ChooseYinYang chooseYinYang; [Header("锁魂塔")] public GameObject curSoulTower; //指挥功能 private float conductTime; //指挥按键长按时间 private int nowConductButton = -1; //现在按下的指挥键(0.J/1.K/2.L/-1.无) private int cacheConductId; [Header("召唤相应时间")] [Tooltip("在此时间内松手为召唤")] public float totalCacheSummonTime; [Header("指挥相应时间")] [Tooltip("在此时间以外松手为指挥")] public float[] canConductTime; [Header("指挥技能")] [Tooltip("选择相应的指挥技能")] public ConductSkills[] conductSkills; public bool[] conductCanRelease; //能否进入指挥技蓄力状态 public ConductReadyTip conductReadyTip; //指挥技就绪 private bool isReadyConduct; [Header("时间倍率")] [Tooltip("时间速度放慢到正常的几倍")] public float timeSlowingMultiplier; public float readyTipFxTime; [Header("转换率")] public float[] conversionRate; //大胖子 [Header("融合临时血量基数")] public int temptHp; [Header("融合血量持续时间")]public float temptTime; public GameObject[] bigGiant; public float[] stageSize; public int[] giantDieNum; //光球 public GameObject photosphereObj; [Header("光球血量基数")] public int photosphereHp; //攻击力 public GameObject attackEffect; //泰山压顶 public GameObject mountain; public Vector3 mountainOffset; //气功波 public GameObject wavePowerObj; [Header("气功波伤害基数")]public int wavePowerDamage; //御剑术 public GameObject flyingSwordsObj; [Header("御剑术伤害")] public int swordsDamage; //怨气弹 public GameObject angryBulletObj; [Header("怨气弹数量基数")] public int angryBulletNum; //扇形飞剑 public GameObject fanFlyingSwords; [Header("飞剑角度范围")]public float flyingSwordsAngleRange; [Header("飞剑角度入射角")] public float flyintSwordsArrivalAngle; [Header("飞剑数量基数")] public int flyingSwordsNum; public enum ConductSkills { Giant, //胖子:合成大胖子 Photosphere, //胖子:光球 AddAttack, //胖子:增加攻击力 Mountain, //气功师:泰山压顶 WavePower, //气功师:气功波 SwordsControl, //气功师:御剑术 AngryBullet, //弓箭手:怨气弹 FlyingSwords, //扇形飞剑 } public bool btnJumpPress { get { //return Input.GetKeyDown(KeyCode.Space) || isClickBtnJump; return isClickBtnJump; } } [HideInInspector] public bool isClickBtnJump; public bool btnRushPress { get { //return Input.GetKeyDown(KeyCode.LeftShift) || isClickBtnRush; return isClickBtnRush; } } [HideInInspector] public bool isClickBtnRush; public bool btnRushKeep { get { //return Input.GetKey(KeyCode.LeftShift) || isKeepBtnRush; return LBisHold || isKeepBtnRush; } } [HideInInspector] public bool isKeepBtnRush; public bool btnTransfiguratePress { get { //return Input.GetKeyDown(KeyCode.L) || isClickBtnEast; return isClickBtnTransfigurate; } } [HideInInspector] public bool isClickBtnTransfigurate; public bool btnEastPress { get { return isClickBtnEast; } } [HideInInspector] public bool isClickBtnEast; public bool btnEastUp { get { return isBtnEastUp; } } [HideInInspector] public bool isBtnEastUp; public bool btnSouthPress { get { //return Input.GetKeyDown(KeyCode.K) || isClickBtnSouth; return isClickBtnSouth; } } [HideInInspector] public bool isClickBtnSouth; public bool btnSouthUp { get { //return Input.GetKeyDown(KeyCode.K) || isClickBtnSouth; return isBtnSouthUp; } } [HideInInspector] public bool isBtnSouthUp; public bool btnWestPress { get { return isClickBtnWest; } } [HideInInspector] public bool isClickBtnWest; public bool btnWestUp { get { return isBtnWestUp; } } [HideInInspector] public bool isBtnWestUp; public bool btnNorthPress { get { return isClickBtnNorth; } } [HideInInspector] public bool isClickBtnNorth; public bool btnNorthUp { get { return isBtnNorthUp; } } [HideInInspector] public bool isBtnNorthUp; public bool btnSpiritSummon { get { //return Input.GetKeyDown(KeyCode.I) || isClickBtnNorth; return isSpiritSummon; } } [HideInInspector] public bool isSpiritSummon; public bool btnSpiritSummon1 { get { //return Input.GetKeyDown(KeyCode.I) || isClickBtnNorth; return isSpiritSummon1; } } [HideInInspector] public bool isSpiritSummon1; public bool btnSpiritSummon2 { get { //return Input.GetKeyDown(KeyCode.I) || isClickBtnNorth; return isSpiritSummon2; } } [HideInInspector] public bool isSpiritSummon2; public bool btnSpiritSummon3 { get { //return Input.GetKeyDown(KeyCode.I) || isClickBtnNorth; return isSpiritSummon3; } } [HideInInspector] public bool isSpiritSummon3; public bool btnNorthKeep { get { //return Input.GetKey(KeyCode.I) || isKeepBtnNorth; return isKeepBtnNorth; } } [HideInInspector] public bool isKeepBtnNorth; public override void Init() { base.Init(); mp = totalMp; uiMp.Show(mp, totalMp); } private void Awake() { PlayerInput playerInput = transform.GetComponent(); spirits = GetComponent(); playerId = playerInput.playerIndex; transform.position = new Vector3(142 + 4 * playerId, 0, 0); playerRope.playerId = playerId; sprintLinkTrigger.playerID = playerId; switch (playerId) { case 0: PlayersInput.instance[0] = this; PlayersInput.instance[1] = this; SpiritSystem.isP1Out = true; SpiritSystem.isP1In = false; SpiritSystem.player1 = gameObject; SpiritSystem.p1Spirits = GetComponent(); break; case 1: PlayersInput.instance[1] = this; SpiritSystem.isP2Out = true; SpiritSystem.isP2In = false; SpiritSystem.player2 = gameObject; SpiritSystem.p2Spirits = GetComponent(); //切换为双人计算蓝量方式 PlayerController p1 = PlayersInput.instance[0]; mpReplySpeed = mpReplySpeed_2Players; p1.mpReplySpeed = mpReplySpeed_2Players; totalMp = totalMp_2Players; p1.totalMp = totalMp_2Players; if (mp > totalMp) { mp = totalMp; } if (p1.mp > totalMp) { p1.mp = totalMp; } uiMp.Show(mp, totalMp); p1.uiMp.Show(p1.mp, totalMp); break; default: break; } skeletonMecanim.skeletonDataAsset = playerSpine[playerId]; demonicDic = new Dictionary>(); for (int i = 0; i < 3; i++) { demonicDic.Add(i, new List()); } Init(); spiritSystem = GameObject.Find("SpiritSystem").GetComponent(); } private void Update() { if (LBisHold) { isKeepBtnRush = true; } if (floatState != 0) { CharacterFloat(); } /* //到时间自动解除变身 if (endChange != 0) { pastChangeTime += Time.deltaTime; if (pastChangeTime >= changeTime) { EndTransfiguration(endChange); endChange = 0; pastChangeTime = 0; } } */ //if (isTransfiguration) //{ // bodyTrans.position = spiritObj.transform.position; //} if (isInvisible) { invisibleTime -= Time.deltaTime; if (invisibleTime <= 0) { isInvisible = false; ChangeMat(1); } } if (haveTransmit) { transmitTime -= Time.deltaTime; if (transmitTime <= 0) { haveTransmit = false; portalsController.rbs.Remove(rb); } } if (rightDir.x < -0.5 || rightDir.x > 0.5) { ChangeSpirit(); } } void OnSprintingPress() { LBisHold = true; isClickBtnRush = true; isKeepBtnRush = true; } void OnSprintingRelease() { LBisHold = false; } //手柄按下LB [HideInInspector] public bool LBisHold; //读取手柄参数 private void OnMove(InputValue value) { if (canMove) { leftDir = value.Get(); } else { leftDir = Vector3.zero; } moveVec = value.Get(); } void OnJump() { if (canJump && canMove) { isClickBtnJump = true; } } void OnSummon0() { if (!isFloat && canMove && nowConductButton == -1) { isClickBtnWest = true; nowConductButton = 0; conductTime = 0; } } void OnSummon0Up() { if (nowConductButton == 0) { isBtnWestUp = true; cacheConductId = nowConductButton; nowConductButton = -1; } } void OnSummon1() { if (!isFloat && canMove && nowConductButton == -1) { isClickBtnSouth = true; nowConductButton = 1; conductTime = 0; } } void OnSummon1Up() { if (nowConductButton == 1) { isBtnSouthUp = true; cacheConductId = nowConductButton; nowConductButton = -1; } } void OnSummon2() { if (!isFloat && canMove && nowConductButton == -1) { isClickBtnEast = true; nowConductButton = 2; conductTime = 0; } } void OnSummon2Up() { if (nowConductButton == 2) { isBtnEastUp = true; cacheConductId = nowConductButton; nowConductButton = -1; } } //选英灵 (手柄右扳机,键盘TAB) void OnChooseSpirit() { switch (playerId) { case 0: SpiritSystem.isP1CardChangeR = true; break; case 1: SpiritSystem.isP2CardChangeR = true; break; default: break; } } //选英灵(手柄右摇杆,小键盘左右) void OnChooseSpirit_LR(InputValue value) { rightDir = value.Get(); } //召唤英灵 void OnTransfigurate() { if (!keyTransfigurateRelease && !isFloat && canMove && !isBaseBtnOut) { isClickBtnTransfigurate = true; } } //松开变身英灵键 void OnTransfigurateUp() { if (!isBaseBtnOut) { keyTransfigurateRelease = true; } } public void Jump() { SetUpSpeed(jumpSpeed); ani.Play("jump", 0, 0); } public void AirJump() { SetUpSpeed(airJumpSpeed); ani.Play("jump", 0, 0); } public void SetUpSpeed(float speed) { ChangeState(CharacterState.Rise); Vector3 velocity = rb.velocity; CheckTurn(); velocity.y = speed; rb.velocity = velocity; //animalAni.SetInteger("state", (int)PlayerState.Rise); } public bool CheckSummon() { if (btnTransfiguratePress) { if (spirits.ultimateTimes[spirits.nowSpirit] > 0) { Summon((int)spirits.ownSpirits[spirits.nowSpirit] + 3); return true; } } if (isBtnEastUp || isBtnWestUp || isBtnSouthUp) { if (cacheSummonTime >= 0 && conductTime <= totalCacheSummonTime) { CheckTurn(); if (!CheckCanSummon(cacheSummonId)) { return false; } Summon(cacheSummonId); return true; } } if (state != CharacterState.Conduct && nowConductButton != -1 && conductTime >= 0) { CheckTurn(); if (conductCanRelease[nowConductButton]) { ChangeState(CharacterState.Conduct); return true; } } return false; } public bool CheckConduct() { if (isBtnEastUp || isBtnWestUp || isBtnSouthUp) { if (isReadyConduct) { Conduct(); } isReadyConduct = false; return true; } if (!isReadyConduct && nowConductButton != -1) { if(conductTime >= totalCacheSummonTime + canConductTime[nowConductButton] * timeSlowingMultiplier) { isReadyConduct = true; } else if( conductTime >= totalCacheSummonTime + (canConductTime[nowConductButton] - readyTipFxTime) * timeSlowingMultiplier) { if (!conductReadyTip.isShowing) { Time.timeScale = timeSlowingMultiplier; conductReadyTip.Show(); } } else { conductReadyTip.Init(); } } return false; } private float TranSize(int dieNum) { for (int i = stageSize.Length - 1; i >= 0; i--) { if (dieNum >= giantDieNum[i]) { if (i == stageSize.Length - 1) { return stageSize[i]; } float size = stageSize[i] + (stageSize[i + 1] - stageSize[i]) / (giantDieNum[i + 1] - giantDieNum[i]) * (dieNum - giantDieNum[i]); return size; } } return 1; } public void Conduct() { int dienum = Mathf.RoundToInt(demonicDic[cacheConductId].Count * conversionRate[cacheConductId]); if (dienum > 0) { GameObject obj; List dieId = new List(); List dieDemonic = new List(); while(dieId.Count t == id)) { dieId.Add(id); dieDemonic.Add(demonicDic[cacheConductId][id]); } } foreach (Demonic d in dieDemonic) { d.ChangeState(CharacterState.Die); } switch (conductSkills[cacheConductId]) { //胖子 case ConductSkills.Giant: GameObject demonicObj = PoolManager.Instantiate(bigGiant[cacheConductId]); Demonic demonic = demonicObj.GetComponent(); int tempthp = dienum * temptHp; demonic.playerID = playerId; demonicObj.transform.parent = null; demonicObj.transform.localEulerAngles = Vector3.zero; demonicObj.transform.localScale = new Vector3(1, 1, 1) * TranSize(dienum); Vector3 offset = demonicSummonPos[0] * 2; if (bodyTrans.localScale.x > 0) { demonicObj.transform.position = transform.position + offset; if (demonic.bodyTrans.localScale.x < 0) { demonic.Turn(); } } else { demonicObj.transform.position = transform.position + new Vector3(-offset.x, offset.y, offset.z); if (demonic.bodyTrans.localScale.x > 0) { demonic.Turn(); } } demonic.player = this; demonic.totalHp = (int)(TranSize(dienum) * demonic.totalHp); demonic.Init(); int order = demonic.baseSortingOrder + demonicDic[demonic.id].Count; demonic.SetSortingOrder(order); if (isInSoulTower) { ls.AddDenomic(demonic); } demonic.GetTemptHP(tempthp, temptTime); break; case ConductSkills.Photosphere: conductCanRelease[cacheConductId] = false; obj = Instantiate(photosphereObj, transform); obj.transform.position = transform.position + Vector3.up; Photosphere photosphere = obj.GetComponent(); photosphere.owner = this; photosphere.conductId = cacheConductId; photosphere.hp = dienum * photosphereHp; break; case ConductSkills.AddAttack: //List newGiants = new List(); //foreach (Demonic d in giants) //{ // if (!d.isDie) // { // newGiants.Add(d); // if (d.addAttackEffect == null) // { // d.addAttackEffect = Instantiate(attackEffect, d.bodyTrans.position, new Quaternion(0, 0, 0, 0), d.bodyTrans); // } // d.addAttackEffect.transform.GetChild(0).gameObject.SetActive(true); // } //} //giants = newGiants; //foreach (Demonic d in giants) //{ // int[] damages = d.curDamage; // for (int i = 0; i < damages.Length; i++) // { // damages[i] += giantNum * swordNum; // } //} break; //气功师 case ConductSkills.Mountain: conductCanRelease[cacheConductId] = false; GameObject curMountain = Instantiate(mountain, null); curMountain.transform.position = transform.position + mountainOffset; Mountain MT = curMountain.GetComponent(); MT.pc = this; MT.id = cacheConductId; MT.demonicNum = dienum; break; case ConductSkills.WavePower: canMove = false; rb.constraints = RigidbodyConstraints.FreezeAll; rb.useGravity = false; conductCanRelease[cacheConductId] = false; obj = Instantiate(wavePowerObj, transform); obj.transform.position = transform.position + Vector3.up; WavePowerSkill wps = obj.GetComponent(); wps.longFX = (int)bodyTrans.localScale.x; wps.damage = wavePowerDamage * dienum; wps.cacheID = cacheConductId; wps.pc = this; break; case ConductSkills.SwordsControl: conductCanRelease[cacheConductId] = false; obj = Instantiate(flyingSwordsObj, transform); obj.transform.position = transform.position + Vector3.up; SwordsControl swordsControl = obj.GetComponentInChildren(); swordsControl.owner = this; swordsControl.conductId = cacheConductId; swordsControl.damage = swordsDamage * dienum; break; //弓箭手 case ConductSkills.AngryBullet: conductCanRelease[cacheConductId] = false; obj = Instantiate(angryBulletObj); AngryBulletControl angryBulletControl = obj.GetComponent(); angryBulletControl.playerController = this; angryBulletControl.cacheConductId = cacheConductId; angryBulletControl.maxNum = dienum * angryBulletNum; break; case ConductSkills.FlyingSwords: obj = Instantiate(fanFlyingSwords); FanFlyingSwords FFS = obj.GetComponent(); FFS.owner = this; FFS.angleRange = flyingSwordsAngleRange; FFS.arrivalAngle = flyintSwordsArrivalAngle; FFS.swordsNum = dienum * flyingSwordsNum; FFS.Biu(); break; } } else { print("使魔不足"); } } //角色处于可自由活动状态时的通用切换状态逻辑,如Idle、Run状态,以及别的状态结束时准备回到Idle状态前 public bool CheckPlayerChangeState(CharacterState excludeState = CharacterState.None) { if (!foot.TrigGround) { //if(excludeState != CharacterState.Summon) //{ // if (CheckSummon()) // { // return true; // } //} if (excludeState != CharacterState.Summon || excludeState != CharacterState.Conduct) { if (CheckSummon()) { return true; } } if ((btnRushPress || cacheRushTime > 0) && mp >= rushCostMp) { if (excludeState != CharacterState.Rush) { ChangeState(CharacterState.Rush); return true; } } if (rb.velocity.y > 0) { if (excludeState != CharacterState.Rise) { ChangeState(CharacterState.Rise); return true; } } else { if (excludeState != CharacterState.Fall) { ChangeState(CharacterState.Fall); return true; } } } else { airJumped = 0; //if (btnNorthPress || cacheAttackTime > 0) //{ // if (excludeState != CharacterState.Attack) // { // Attack1(); // return true; // } //} if (eventTrigger.triggedRivet && (btnNorthPress || cachePullRopeTime > 0)) { if (sprintLinkTrigger.linkedEnemy.Count > 0) { eventTrigger.triggedRivet.BindingRopes(sprintLinkTrigger.linkedEnemy); } //ChangeState(CharacterState.PullRope); } if (excludeState != CharacterState.Summon || excludeState != CharacterState.Conduct) { if (CheckSummon()) { return true; } } if ((btnRushPress || cacheRushTime > 0) && mp >= rushCostMp) { if (excludeState != CharacterState.Rush) { ChangeState(CharacterState.Rush); return true; } } if (btnJumpPress || cacheJumpTime > 0) { if (excludeState != CharacterState.Rise) { Jump(); ChangeState(CharacterState.Rise); return true; } } if (leftDir.y < -0.5) { Platform platform = foot.trigGroundList[0].GetComponent(); if (platform != null && platform.canDown) { foot.trigGroundList.Remove(platform.gameObject); } } if (canfly) { if (leftDir.x > 0.3f || leftDir.x < -0.3f || leftDir.y > 0.3f || leftDir.y < -0.3f) { if (excludeState != CharacterState.Run) { ChangeState(CharacterState.Run); return true; } } else { if (excludeState != CharacterState.Idle) { ChangeState(CharacterState.Idle); return true; } } } else { if (leftDir.x > 0.3f || leftDir.x < -0.3f) { if (excludeState != CharacterState.Run) { ChangeState(CharacterState.Run); return true; } } else { if (excludeState != CharacterState.Idle) { ChangeState(CharacterState.Idle); return true; } } } } return false; } public override Vector3 GetMoveDir() { return leftDir; } public void CachedPlayerInput() { if (btnRushPress) { cacheRushTime = totalCacheRushTime; } if (btnJumpPress) { cacheJumpTime = totalCacheJumpTime; } if (btnNorthPress) { cacheAttackTime = totalCacheAttackTime; } if (btnWestPress) { cacheSummonTime = totalCacheSummonTime; cacheSummonId = 0; } if (btnSouthPress) { cacheSummonTime = totalCacheSummonTime; cacheSummonId = 1; } if (btnEastPress) { cacheSummonTime = totalCacheSummonTime; cacheSummonId = 2; } //if (btnSpiritSummon) //{ // cacheSummonTime = totalCacheSummonTime; // cacheSummonId = 3; //} //if (btnSpiritSummon1) //{ // cacheSummonTime = totalCacheSummonTime; // cacheSummonId = 4; //} //if (btnSpiritSummon2) //{ // cacheSummonTime = totalCacheSummonTime; // cacheSummonId = 5; //} //if (btnSpiritSummon3) //{ // cacheSummonTime = totalCacheSummonTime; // cacheSummonId = 6; //} } public override void OnState() { base.OnState(); cacheJumpTime -= Time.deltaTime; cacheAttackTime -= Time.deltaTime; cacheSummonTime -= Time.deltaTime; canJumpTime -= Time.deltaTime; invincibleTime -= Time.deltaTime; attackTime -= Time.deltaTime; summonTime -= Time.deltaTime; rushTime -= Time.deltaTime; cacheRushTime -= Time.deltaTime; dieKeepTime -= Time.deltaTime; weakTime -= Time.deltaTime; beRepelValue += Time.deltaTime; if (nowConductButton != -1) { conductTime += Time.deltaTime; } CachedPlayerInput(); Vector3 velocity = rb.velocity; switch (state) { case CharacterState.Idle: if (CheckPlayerChangeState(CharacterState.Idle)) { break; } rb.velocity = Vector3.right * velocityAddition; break; case CharacterState.Run: if (CheckPlayerChangeState(CharacterState.Run)) { break; } CheckTurn(); if (canfly) { rb.velocity = leftDir.normalized * moveSpeed; } else { if (leftDir.x > 0.3f) { rb.velocity = new Vector3(moveSpeed + velocityAddition, 0, 0); } else if (leftDir.x < -0.3f) { rb.velocity = new Vector3(-moveSpeed + velocityAddition, 0, 0); } } break; case CharacterState.Rise: if (CheckSummon()) { break; } if ((btnRushPress || cacheRushTime > 0) && mp >= rushCostMp) { ChangeState(CharacterState.Rush); break; } if (btnJumpPress || cacheJumpTime > 0) { if (airJumped < airJumpNumber && rb.velocity.y < canAirJumpSpeed) { airJumped++; AirJump(); break; } } rb.velocity = AirMove(rb.velocity); if (rb.velocity.y <= 0) { ChangeState(CharacterState.Fall); break; } break; case CharacterState.Fall: if (CheckSummon()) { break; } if ((btnRushPress || cacheRushTime > 0) && mp >= rushCostMp) { ChangeState(CharacterState.Rush); break; } if (foot.TrigGround) { if (CheckPlayerChangeState()) { break; } } //if (foot.canStepPlayers.Count > 0) //{ // Jump(jumpSpeed / 2); // StepOther(); // break; //} //if (foot.canStepEnemyList.Count > 0) //{ // Jump(jumpSpeed / 2); // StepEnemy(); // break; //} if (btnJumpPress || cacheJumpTime > 0) { if (canJumpTime > 0) { Jump(); break; } else { if (airJumped < airJumpNumber) { airJumped++; AirJump(); break; } } } rb.velocity = AirMove(rb.velocity); break; //case CharacterState.Hurt: // if (hurtKeepTime <= 0 && rb.velocity.magnitude < hurtChangeVelocity) // { // if (CheckPlayerChangeState()) // { // break; // } // } // Vector3 vel = rb.velocity; // if (!foot.TrigGround) // { // if (canfly) // { // vel.y = vel.y * (1 - decelerationRatio * Time.deltaTime); // } // else // { // vel += Vector3.up * extraFallGravity * Time.deltaTime; // } // } // vel.x = vel.x * (1 - decelerationRatio * Time.deltaTime); // rb.velocity = vel; // CachedPlayerInput(); // break; case CharacterState.Coma: break; case CharacterState.Attack: if (attackTime <= 0) { if (btnNorthKeep) { ChangeState(CharacterState.KeepAttack); break; } if (CheckPlayerChangeState()) { break; } } break; case CharacterState.KeepAttack: if ((btnRushPress) && mp >= rushCostMp) { ChangeState(CharacterState.Rush); break; } if (btnJumpPress && canJumpTime > 0) { Jump(); break; } if (!btnNorthKeep) { if (CheckPlayerChangeState(CharacterState.Attack)) { break; } } switch (attackState) { case PlayerAttackState.Idle: if (bodyTrans.localScale.x > 0) { if (leftDir.x > 0.3f) { SetAttackState(PlayerAttackState.WalkBack); velocity.x = attackMoveSpeed; rb.velocity = velocity; break; } else if (leftDir.x < -0.3f) { SetAttackState(PlayerAttackState.WalkForward); velocity.x = -attackMoveSpeed; rb.velocity = velocity; break; } } else { if (leftDir.x > 0.3f) { SetAttackState(PlayerAttackState.WalkForward); velocity.x = attackMoveSpeed; rb.velocity = velocity; break; } else if (leftDir.x < -0.3f) { SetAttackState(PlayerAttackState.WalkBack); velocity.x = -attackMoveSpeed; rb.velocity = velocity; break; } } velocity.x = 0; rb.velocity = velocity; break; case PlayerAttackState.WalkForward: if (bodyTrans.localScale.x > 0) { if (leftDir.x > 0.3f) { SetAttackState(PlayerAttackState.WalkBack); velocity.x = attackMoveSpeed; rb.velocity = velocity; break; } else if (leftDir.x > -0.3f && leftDir.x < 0.3f) { SetAttackState(PlayerAttackState.Idle); velocity.x = 0; rb.velocity = velocity; break; } else { velocity.x = -attackMoveSpeed; rb.velocity = velocity; } } else { if (leftDir.x < -0.3f) { SetAttackState(PlayerAttackState.WalkBack); velocity.x = -attackMoveSpeed; rb.velocity = velocity; break; } else if (leftDir.x > -0.3f && leftDir.x < 0.3f) { SetAttackState(PlayerAttackState.Idle); velocity.x = 0; rb.velocity = velocity; break; } else { velocity.x = attackMoveSpeed; rb.velocity = velocity; } } break; case PlayerAttackState.WalkBack: if (bodyTrans.localScale.x > 0) { if (leftDir.x < -0.3f) { SetAttackState(PlayerAttackState.WalkForward); velocity.x = -attackMoveSpeed; rb.velocity = velocity; break; } else if (leftDir.x > -0.3f && leftDir.x < 0.3f) { SetAttackState(PlayerAttackState.Idle); velocity.x = 0; rb.velocity = velocity; break; } else { velocity.x = attackMoveSpeed; rb.velocity = velocity; } } else { if (leftDir.x > 0.3f) { SetAttackState(PlayerAttackState.WalkForward); velocity.x = attackMoveSpeed; rb.velocity = velocity; break; } else if (leftDir.x > -0.3f && leftDir.x > 0.3f) { SetAttackState(PlayerAttackState.Idle); velocity.x = 0; rb.velocity = velocity; break; } else { velocity.x = -attackMoveSpeed; rb.velocity = velocity; } } break; default: break; } break; case CharacterState.Summon: if (summonTime <= 0 || btnTransfiguratePress) { if (CheckPlayerChangeState()) { break; } } rb.velocity = Vector3.right * velocityAddition; if (leftDir.x > 0.3f || leftDir.x < -0.3f) { cacheDir = leftDir.x; } break; case CharacterState.Rush: if (rushTime <= 0) { if (btnRushKeep) { ChangeState(CharacterState.Sprint); break; } if (CheckPlayerChangeState()) { break; } } //if (leftDir.magnitude < 0.3f) //{ // if (bodyTrans.localScale.x > 0) // { // rushDir = Vector3.left; // } // else // { // rushDir = Vector3.right; // } //} //else //{ // rushDir = leftDir.normalized; //} rb.velocity = rushDir * rushSpeed; break; case CharacterState.Sprint: if (!btnRushKeep) { if (CheckPlayerChangeState(CharacterState.Rush)) { break; } } if (mp < sprintCostMp * Time.deltaTime) { if (CheckPlayerChangeState(CharacterState.Rush)) { break; } } mp -= sprintCostMp * Time.deltaTime; uiMp.Show(mp, totalMp); //CheckTurn(); //if (leftDir.magnitude < 0.3f) //{ // if (bodyTrans.localScale.x > 0) // { // rushDir = Vector3.left; // } // else // { // rushDir = Vector3.right; // } //} //else //{ // rushDir = leftDir.normalized; //} rb.velocity = rushDir * rushSpeed; break; case CharacterState.Die: if (dieKeepTime <= 0) { if (isRevive) { reviveTime += Time.deltaTime; if (reviveTime >= totalReviveTime) { PlayerRevive(); } } else { PlayerDie(); } } break; case CharacterState.Weak: if (rb.velocity.magnitude > 1) { if (ani.GetCurrentAnimatorClipInfo(0)[0].clip.name != "hitted") { ani.Play("hitted", 0, 0); aniCollider.Play("Hurt", 0, 0); } Vector3 vel = rb.velocity; if (!canfly) { if (foot.TrigGround && vel.y < 0) { vel.y = 0; } else { vel += Vector3.up * extraFallGravity * Time.deltaTime; } } vel.y = vel.y * (1 - decelerationRatio * Time.deltaTime); vel.x = vel.x * (1 - decelerationRatio * Time.deltaTime); rb.velocity = vel; } else { if (ani.GetCurrentAnimatorClipInfo(0)[0].clip.name != "weak") { ani.Play("weak", 0, 0); aniCollider.Play("Weak", 0, 0); rb.velocity = Vector3.zero; weakTime = totalWeakTime; } rb.velocity = new Vector3(velocityAddition, rb.velocity.y, 0); } if (weakTime <= 0) { ChangeState(CharacterState.Idle); break; } break; case CharacterState.PullRope: break; case CharacterState.Conduct: if (CheckSummon()) { break; } if (CheckConduct()) { ChangeState(CharacterState.Idle); } break; default: break; } if (!foot.TrigGround && !canfly) { if (rb.velocity.y > 0) { rb.velocity += Vector3.up * extraRiseGravity * Time.deltaTime; } else { rb.velocity += Vector3.up * extraFallGravity * Time.deltaTime; } } isClickBtnRush = false; isKeepBtnRush = false; isClickBtnJump = false; isClickBtnSouth = false; isClickBtnEast = false; isClickBtnNorth = false; isClickBtnWest = false; isBtnSouthUp = false; isBtnEastUp = false; isBtnNorthUp = false; isBtnWestUp = false; isSpiritSummon = false; isSpiritSummon1 = false; isSpiritSummon2 = false; isSpiritSummon3 = false; isClickBtnTransfigurate = false; keyTransfigurateRelease = false; if (foot.TrigGround) { canJumpTime = leaveGroundCanJumpTime; } SearchTarget(); attackTarget = targetCharacter; if (isMpRepel && floatState == 0) { if (mp < totalMp) { if (!isRapedReply) { mp += mpReplySpeed * Time.deltaTime; } else { mp += rapidReplySpeed * Time.deltaTime; } } } if (floatState != 0) { if (mp > 0) { lostMp += mpReplySpeed * Time.deltaTime; mp -= mpReplySpeed * Time.deltaTime; } if (lostMp >= addMp) { Instantiate(soul, transform.position, new Quaternion(0, 0, 0, 0), null); lostMp = 0; } } if (mp > totalMp) { mp = totalMp; } if (mp < 0) { mp = 0; } uiMp.Show(mp, totalMp); } public void PlayerDie() { switch (playerId) { case 0: SpiritSystem.isP1In = true; SpiritSystem.isP1Out = false; break; case 1: SpiritSystem.isP2In = true; SpiritSystem.isP2Out = false; break; default: break; } foot.trigGroundList.Clear(); bodyTrans.gameObject.SetActive(false); uiHp.transform.parent.gameObject.SetActive(false); rb.constraints = RigidbodyConstraints.FreezeAll; isRevive = true; reviveTime = 0; } public void PlayerRevive() { isRevive = false; isBaseBtnOut = false; bodyTrans.gameObject.SetActive(true); uiHp.transform.parent.gameObject.SetActive(true); rb.constraints = RigidbodyConstraints.FreezePositionZ | RigidbodyConstraints.FreezeRotation; transform.position = new Vector3(142 + 4 * playerId, 0, 0); switch (playerId) { case 0: SpiritSystem.isP1In = false; SpiritSystem.isP1Out = true; SpiritSystem.player1 = gameObject; SpiritSystem.p1Spirits = GetComponent(); break; case 1: SpiritSystem.isP2In = false; SpiritSystem.isP2Out = true; SpiritSystem.player2 = gameObject; SpiritSystem.p2Spirits = GetComponent(); break; default: break; } Init(); } public void RapidReplyMp() { isRapedReply = true; rapidReplyEffect.SetActive(true); } public void NormalReplyMp() { isRapedReply = false; rapidReplyEffect.SetActive(false); } public override void ChangeState(CharacterState newState) { if (state == newState) { return; } if (newState == CharacterState.Weak) { return; } Vector3 velocity = rb.velocity; switch (state) { case CharacterState.Idle: break; case CharacterState.Run: velocity.x = 0; break; case CharacterState.Rise: bodyCollider.SetActive(true); break; case CharacterState.Fall: break; //case CharacterState.Hurt: // break; case CharacterState.Coma: canMove = true; break; case CharacterState.Attack: aniCollider.Play("NotAttack", 1, 0); break; case CharacterState.KeepAttack: aniCollider.Play("NotAttack", 1, 0); break; case CharacterState.Summon: rb.isKinematic = false; if (cacheDir != 0) { if (cacheDir > 0.3f && bodyTrans.localScale.x > 0) { Turn(); } else if (cacheDir < -0.3f && bodyTrans.localScale.x < 0) { Turn(); } cacheDir = 0; } break; case CharacterState.Transfiguration: rb.isKinematic = false; break; case CharacterState.Rush: velocity = Vector3.zero; break; case CharacterState.Sprint: velocity = Vector3.zero; break; case CharacterState.Die: if (isRevive) { return; } isDie = false; break; case CharacterState.Weak: beRepelValue = totalBeRepelValue; break; case CharacterState.Conduct: rb.isKinematic = false; Time.timeScale = 1; break; default: break; } CharacterState oldState = state; state = newState; switch (newState) { case CharacterState.Idle: aniCollider.Play("Idle", 0, 0); if (oldState == CharacterState.Fall) { ani.Play("fall_end", 0, 0); } else { ani.Play("idle", 0, 0); } velocity = Vector3.right * velocityAddition; //animalAni.SetInteger("state", (int)PlayerState.Idle); break; case CharacterState.Run: aniCollider.Play("Run", 0, 0); ani.Play("run_start", 0, 0); //animalAni.SetInteger("state", (int)PlayerState.Walk); break; case CharacterState.Rise: aniCollider.Play("Rise", 0, 0); canJumpTime = 0; break; case CharacterState.Fall: aniCollider.Play("Fall", 0, 0); ani.Play("fall", 0, 0); //animalAni.SetInteger("state", (int)PlayerState.Fall); break; //case CharacterState.Hurt: // aniCollider.Play("Hurt", 0, 0); // ani.Play("hitted", 0, 0); // invincibleTime = totalInvincibleTime; // hurtKeepTime = minHurtKeepTime; // //ani.Play("Invincible", 2, 0); // break; case CharacterState.Coma: //ani.Play("Coma", 0, 0); ani.Play("idle", 0, 0); aniCollider.Play("Idle", 0, 0); rb.velocity = Vector3.zero; break; case CharacterState.Attack: attackTime = totalAttack1Time; break; case CharacterState.KeepAttack: aniCollider.Play("Attack1Keep", 1, 0); break; case CharacterState.Summon: aniCollider.Play("Summon", 0, 0); ani.Play("summon", 0, 0); velocity = Vector3.right * velocityAddition; rb.isKinematic = true; cacheDir = 0; break; case CharacterState.Transfiguration: aniCollider.Play("Transfiguration", 0, 0); ani.Play("transfiguration", 0, 0); velocity = Vector3.zero; rb.isKinematic = true; break; case CharacterState.Rush: aniCollider.Play("Rush", 0, 0); ani.Play("rush_loop", 0, 0); rushTime = totalRushTime; invincibleTime = rushInvincibleTime; //if (leftDir.magnitude < 0.3f) //{ // if (bodyTrans.localScale.x > 0) // { // rushDir = Vector3.left; // } // else // { // rushDir = Vector3.right; // } //} //else //{ // rushDir = leftDir.normalized; //} if (bodyTrans.localScale.x > 0) { rushDir = Vector3.left; } else { rushDir = Vector3.right; } velocity = rushDir * rushSpeed; mp -= rushCostMp; uiMp.Show(mp, totalMp); break; case CharacterState.Sprint: aniCollider.Play("Sprint", 0, 0); ani.Play("rush_loop", 0, 0); velocity = rushDir * rushSpeed; break; case CharacterState.Die: aniCollider.Play("Die", 0, 0); ani.Play("die", 0, 0); isDie = true; dieKeepTime = totalDieKeepTime; break; case CharacterState.Weak: weakTime = totalWeakTime; //hurtKeepTime = minHurtKeepTime; break; case CharacterState.Conduct: rb.velocity = Vector3.zero; rb.isKinematic = true; aniCollider.Play("Summon", 0, 0); ani.Play("summon", 0, 0); break; default: break; } rb.velocity = velocity; } public void CheckTurn() { if (leftDir.x > 0.3f && bodyTrans.localScale.x > 0) { Turn(); } else if (leftDir.x < -0.3f && bodyTrans.localScale.x < 0) { Turn(); } } public Vector3 AirMove(Vector3 velocity) { CheckTurn(); if (canfly) { velocity = leftDir.normalized * flySpeed; if (transform.position.y > maxFlyHeight && velocity.y > 0) { velocity.y = 0; } } else { if (leftDir.x > 0.3f) { velocity = new Vector3(moveSpeed, velocity.y, velocity.z); } else if (leftDir.x < -0.3f) { velocity = new Vector3(-moveSpeed, velocity.y, velocity.z); } else { velocity = new Vector3(0, velocity.y, velocity.z); } } return velocity; } public void Transfiguration(int id) //变身 { id = id - 3; if (id >= changePrefabs.Count) { Debug.LogError("未配置" + id + "号变身"); return; } GameObject prefab = changePrefabs[id]; ChangeState(CharacterState.Transfiguration); summonTime = prefab.GetComponent().totalSummonTime; bodyTrans.gameObject.SetActive(false); foot.trigGroundList.Clear(); spiritObj = PoolManager.Instantiate(prefab); Demonic dem = spiritObj.GetComponent(); dem.id = id; dem.playerID = playerId; spiritObj.transform.parent = transform; spiritObj.transform.localEulerAngles = Vector3.zero; spiritObj.transform.localScale = new Vector3(1, 1, 1); if (bodyTrans.localScale.x > 0) { spiritObj.transform.position = transform.position; if (dem.bodyTrans.localScale.x < 0) { dem.Turn(); } } else { spiritObj.transform.position = transform.position; if (dem.bodyTrans.localScale.x > 0) { dem.Turn(); } } mecanim = dem.mecanim; ani = dem.ani; aniCollider = dem.aniCollider; bodyTrans = dem.bodyTrans; beSearchTrigger = dem.beSearchTrigger; bulletPrefab = dem.bulletPrefab; searchTrigger = dem.searchTrigger; foot = dem.foot; spinee = dem.spinee; mesh = dem.mesh; mats = dem.mats; soulCollector = dem.soulCollector; outlineMats = dem.outlineMats; if (dem.canFly) { canfly = true; canJump = false; rb.useGravity = false; } /* 法师出场释放浮空场 if (id == 3) { if ((int)spirits.currentSpirit == 0) { if (!spiritObj.GetComponent().hasEffect) { spiritObj.GetComponent().hasEffect = true; Instantiate(spirits.floatEffect, spiritObj.transform.position, new Quaternion(0, 0, 0, 0), spiritObj.transform); } } } */ endChange = id + 3; curHp = hp; curTotalHp = totalHp; uiHp.Show(hp, totalHp); ChangeState(CharacterState.Idle); } public void Summon(int id) { if (id >= demonicPrefabs.Count) { Debug.LogError("未配置" + id + "号使魔"); return; } if (id >= demonicSummonPos.Count) { Debug.LogError("未配置" + id + "号使魔召唤位置"); return; } GameObject prefab; if (id == 1) { prefab = chooseYinYang.SelectPrefab(playerId); } else { prefab = demonicPrefabs[id]; } if (!CheckCanSummon(id)) { return; } ChangeState(CharacterState.Summon); summonTime = prefab.GetComponent().totalSummonTime; float costMp = prefab.GetComponent().costMp; mp -= costMp; uiMp.Show(mp, totalMp); GameObject demonicObj = PoolManager.Instantiate(prefab); Demonic demonic = demonicObj.GetComponent(); demonic.id = id; demonic.playerID = playerId; if (!demonicDic.ContainsKey(id)) { demonicDic.Add(id, new List()); } demonicDic[id].Add(demonic); demonicObj.transform.parent = null; demonicObj.transform.localEulerAngles = Vector3.zero; demonicObj.transform.localScale = new Vector3(1, 1, 1); Vector3 offset = demonicSummonPos[id]; if (bodyTrans.localScale.x > 0) { demonicObj.transform.position = transform.position + offset; if (demonic.bodyTrans.localScale.x < 0) { demonic.Turn(); } } else { demonicObj.transform.position = transform.position + new Vector3(-offset.x, offset.y, offset.z); if (demonic.bodyTrans.localScale.x > 0) { demonic.Turn(); } } if (demonic.canFly) { demonic.flyHeight = demonic.transform.position.y; } demonic.player = this; demonic.Init(); int order = prefab.GetComponent().baseSortingOrder + demonicDic[demonic.id].Count; demonic.SetSortingOrder(order); if (id != 4) { demonic.Attack1(); } //id 3~6 为四个英灵 if (id >= 3 && id <= 6) { spirits.ultimateTimes[spirits.nowSpirit] -= 1; } spiritSystem.RefreshPlayerUI(); if (isInSoulTower) { ls.AddDenomic(demonic); } } public void OnDemonicRecycle(Demonic demonic) { if (!demonicDic.ContainsKey(demonic.id)) { return; } demonicDic[demonic.id].Remove(demonic); for (int i = 0; i < demonicDic[demonic.id].Count; i++) { int order = demonicDic[demonic.id][i].baseSortingOrder + i; demonicDic[demonic.id][i].SetSortingOrder(order); } } public bool CheckCanSummon(int id) { GameObject prefab; if (id == 1) { prefab = chooseYinYang.SelectPrefab(playerId); } else { prefab = demonicPrefabs[id]; } float costMp = prefab.GetComponent().costMp; if (mp < costMp) { Debug.Log("mp不足召唤失败, 还得加个动画或者音效啥的"); return false; } return true; } public override void Attack1() { base.Attack1(); if (leftDir.x > 0.3f) { if (bodyTrans.localScale.x > 0) { Turn(); } SetAttackState(PlayerAttackState.WalkForward); } else if (leftDir.x < -0.3f) { if (bodyTrans.localScale.x < 0) { Turn(); } SetAttackState(PlayerAttackState.WalkForward); } else { SetAttackState(PlayerAttackState.Idle); } } public void SetAttackState(PlayerAttackState value) { attackState = value; ani.SetInteger("attackState", (int)value); aniCollider.Play("Attack1Keep", 1, 0); } public void SearchTarget() { targetCharacter = searchTrigger.GetMinDisTarget(targetTypes, canHitFly); } public void ChangeSpirit() { if ((playerId == 0 && SpiritSystem.canP1CardChange) || (playerId == 1 && SpiritSystem.canP2CardChange)) { if (rightDir.x >= 0.5) { switch (playerId) { case 0: SpiritSystem.P1CardChangeTime = 0; SpiritSystem.canP1CardChange = false; SpiritSystem.isP1CardChangeR = true; break; case 1: SpiritSystem.P2CardChangeTime = 0; SpiritSystem.canP2CardChange = false; SpiritSystem.isP2CardChangeR = true; break; default: break; } } else if (rightDir.x <= -0.5) { switch (playerId) { case 0: SpiritSystem.P1CardChangeTime = 0; SpiritSystem.canP1CardChange = false; SpiritSystem.isP1CardChangeL = true; break; case 1: SpiritSystem.P2CardChangeTime = 0; SpiritSystem.canP2CardChange = false; SpiritSystem.isP2CardChangeL = true; break; default: break; } } } } }