//建造状态机 private void MakeFSM() { InspectionState inspection = new InspectionState(); inspection.AddTransition(Transition.SawPlayer, StateID.ChasingPlayer); inspection.AddTransition(Transition.LostPlayer, StateID.FollowingPath); PatrolState follow = new PatrolState(transform.position, scope); follow.AddTransition(Transition.SawPlayer, StateID.ChasingPlayer); follow.AddTransition(Transition.ArrivePath, StateID.Inspection); ChasePlayerState chase = new ChasePlayerState(); chase.AddTransition(Transition.LostPlayer, StateID.FollowingPath); chase.AddTransition(Transition.NearPlayer, StateID.AttackPlayer); AttackPlayerState attack = new AttackPlayerState(); attack.AddTransition(Transition.LostPlayer, StateID.FollowingPath); fsm = new FsmSystem(); fsm.AddState(inspection);//添加状态到状态机,第一个添加的状态将作为初始状态 fsm.AddState(follow); fsm.AddState(chase); fsm.AddState(attack); }
private void AddAttempt(AttackPlayerState attack) { HitAttemptStats stats = new HitAttemptStats(attack.name); hitAttemptDictionary.Add(GameManager.Instance.FrameCounter, stats); lastHitStatsFrame = GameManager.Instance.FrameCounter; Attempts++; }
public void Awake() { distToGround = GetComponent <BoxCollider2D>().bounds.extents.y; //Debug.Log("Awake start"); _stateMachine = new StateMachine(); var idle = new IdlePlayerState(this, _rigidbody2D); var move = new MovePlayerState(this, _rigidbody2D, _animator); var attack = new AttackPlayerState(this, _animator); var jump = new JumpPlayerState(this, _rigidbody2D, _animator); var airborne = new AirbornePlayerState(this, _rigidbody2D, _animator); var death = new DeathPlayerState(this); At(idle, move, isMoving()); At(move, idle, isIdle()); At(idle, jump, isJumping()); At(move, jump, isJumping()); At(jump, airborne, isJumping()); At(airborne, idle, isGrounded()); At(airborne, move, isGrounded()); At(idle, attack, isAttacking()); At(jump, attack, isAttacking()); At(airborne, attack, isAttacking()); At(move, attack, isAttacking()); At(attack, idle, isIdle()); At(attack, move, isMoving()); At(attack, airborne, isAirborne()); At(idle, death, isDead()); At(jump, death, isDead()); At(airborne, death, isDead()); At(move, death, isDead()); At(death, idle, isAlive()); Func <bool> isIdle() => () => MoveVal == 0 && Physics2D.Raycast(transform.position, Vector2.down, distToGround + 0.05f, _jumpLayerMask); Func <bool> isMoving() => () => MoveVal != 0 && !Jumped && Physics2D.Raycast(transform.position, Vector2.down, distToGround + 0.05f, _jumpLayerMask); Func <bool> isJumping() => () => Jumped; Func <bool> isGrounded() => () => Physics2D.Raycast(transform.position, Vector2.down, distToGround + 0.05f, _jumpLayerMask); Func <bool> isAirborne() => () => !Physics2D.Raycast(transform.position, Vector2.down, distToGround + 0.05f, _jumpLayerMask); Func <bool> isAttacking() => () => Attacked; Func <bool> isDead() => () => health <= 0; Func <bool> isAlive() => () => health > 0; void At(IState from, IState to, Func <bool> condition) => _stateMachine.AddTransition(from, to, condition); //Debug.Log("Awake end"); _stateMachine.SetState(idle); }
public void OnPlayerAttackEnded(Player player, AttackPlayerState attack) { HitAttemptStats stats = hitAttemptDictionary[lastHitStatsFrame]; if ((stats.ResultType != ResultType.SUCCESS) && validInitFramesDictionary.ContainsKey(attack.name)) { CalculateLateStats(stats, attack); } RemoveListeners(attack); }
public void OnPlayerEnteredState(EntityState state) { if (state is AttackPlayerState) { AttackPlayerState attack = (AttackPlayerState)state; attack.name = attack.name.Replace("(Clone)", "").Trim(); AddAttempt(attack); attack.OnHitEvent.AddListener(OnPlayerAttackHit); attack.OnEndEvent.AddListener(OnPlayerAttackEnded); } }
private void PerAttackFrameIntersectionCheck(Bounds centeredFocusBounds, AttackPlayerState attack) { //List<int> validInitFrames; ValidInitFrames validInitFrames; if (validInitFramesDictionary.ContainsKey(attack.name)) { validInitFrames = validInitFramesDictionary[attack.name]; } else { validInitFrames = new ValidInitFrames(); validInitFramesDictionary.Add(attack.name, validInitFrames); } //get old behaviour by clearing the frameCounter here //reset valid init frames //validInitFrames.Clear(); int position = 1; for (float normalizedCurrentFrame = 0.0f; normalizedCurrentFrame < attack.FrameData.Frames.Length; normalizedCurrentFrame += Time.timeScale * attack.FrameData.PlayBackSpeed) { Frame frame = attack.FrameData.Frames[(int)normalizedCurrentFrame]; foreach (Box box in frame.Boxes) { if (box is HitBox && (centeredFocusBounds.Intersects(box.GetRelativeBounds(player)))) { validInitFrames.AddToFrameSet(GameManager.Instance.FrameCounter - position); break; } } position++; } //sort in ascending order /* make sure stats for last hit are present, this may not be the case if e.g. the player * hasn't attacked yet */ if (hitAttemptDictionary.ContainsKey(lastHitStatsFrame)) { HitAttemptStats stats = hitAttemptDictionary[lastHitStatsFrame]; if ((stats.ResultType != ResultType.SUCCESS) && validInitFramesDictionary.ContainsKey(attack.name)) { CalculateEarlyStats(stats, attack); } } }
private void MakeFSM() { FollowPathState follow = new FollowPathState(path); follow.AddTransition(Transition.SawPlayer, StateID.ChasePlayer); ChasePlayerState chase = new ChasePlayerState(); chase.AddTransition(Transition.LostPlayer, StateID.FollowPath); chase.AddTransition(Transition.NearPlayer, StateID.AttackPlayer); AttackPlayerState attack = new AttackPlayerState(); attack.AddTransition(Transition.SawPlayer, StateID.ChasePlayer); sm = new FSMSystem(); sm.AddState(follow); sm.AddState(chase); sm.AddState(attack); }
private BoundsData ExtractPlayerAttackBounds(AttackPlayerState playerAttack) { Bounds bounds = new Bounds(); foreach (Frame frame in playerAttack.FrameData.Frames) { foreach (Box box in frame.Boxes) { if (box is HitBox) { bounds.Encapsulate(box.BoundsData.GetBounds()); } } } return(new BoundsData(bounds.center, bounds.size)); }
public void PerformChargedAttack(Player player) { Frame[] frames = GetChargedFrames(); FrameData frameData = ScriptableObject.CreateInstance <FrameData>(); frameData.Frames = frames; frameData.SpriteList = attack.FrameData.SpriteList; frameData.Sprites = attack.FrameData.Sprites; frameData.PlayBackSpeed = attack.FrameData.PlayBackSpeed; AttackPlayerState chargedAttack = UnityEngine.Object.Instantiate(attack); chargedAttack.FrameData = frameData; player.State = chargedAttack; }
private void CalculateDeltaStats(HitAttemptStats stats, AttackPlayerState attack, float maxThreshold) { List <int> validInitFrames = validInitFramesDictionary[attack.name].FrameCounts; if (validInitFrames.Count > 0) { foreach (int frame in validInitFrames) { int frameDelta = lastHitStatsFrame - frame; //if delta within maximum alotted threshold if (Mathf.Abs(frameDelta) < maxThreshold) { stats.AddToHitFrameDeltaSet(frameDelta); } } } }
private void AddHit(AttackPlayerState attack) { HitAttemptStats stats = hitAttemptDictionary[lastHitStatsFrame]; if (!stats.AttackName.Equals(attack.name)) { Debug.LogError("Invalid hit add"); return; } //only count hits once for multi-hit moves if ((stats.ResultType != ResultType.SUCCESS)) { Hits++; } stats.ResultType = ResultType.SUCCESS; stats.MinHitFrameDelta = 0; }
private void MakeFSM() { StayStillState stay = new StayStillState(); stay.AddTransition(Transition.SawPlayer, StateID.ChasingPlayer); ChasePlayerState chase = new ChasePlayerState(); chase.AddTransition(Transition.LostPlayer, StateID.FindPlayer); chase.AddTransition(Transition.ReachPlayer, StateID.AttackPlayer); AttackPlayerState attack = new AttackPlayerState(); attack.AddTransition(Transition.LostPlayer, StateID.ChasingPlayer); //StayStillState stay = new StayStillState(); fsm = new FSMSystem(); fsm.AddState(stay); fsm.AddState(chase); fsm.AddState(attack); //fsm.AddState(stay); fsm.SetCurrentState(stay); }
private void RemoveListeners(AttackPlayerState attack) { attack.OnHitEvent.RemoveListener(OnPlayerAttackHit); attack.OnEndEvent.RemoveListener(OnPlayerAttackEnded); }
private void CalculateEarlyStats(HitAttemptStats stats, AttackPlayerState attack) { CalculateDeltaStats(stats, attack, maxEarlyThreshold); }
public void OnPlayerAttackHit(Player player, AttackPlayerState attack) { AddHit(attack); }