1.實現瞄準狀態和接劍狀態
準備好瞄準動畫,投擲動畫和接劍動畫,并設置參數AimSword和CatchSword
投擲動畫在瞄準動畫后,瞄準結束后才能投擲
創建PlayerAimSwordState腳本和PlayerCatchSwordState腳本并在Player中初始化:
PlayerAimSwordState腳本:
? ? ? ? if(Input.GetKeyDown(KeyCode.Mouse1))//鼠標右鍵
{
_PlayerStateMachine.ChangeState(_Player.idleState);
}//在Update中,用于調試
PlayerGroundedState腳本:
? ? ? ? if(Input.GetKeyDown(KeyCode.Mouse1))
{
_PlayerStateMachine.ChangeState(_Player.AimSword);
}
為SkillManage對象創建新腳本Sword_Skil并在SkillManage腳本中初始化它:
? ? [Header("Skill info")]
[SerializeField] private GameObject swordPrefab;//劍的預制體
[SerializeField] private Vector2 lanchForce;//劍的發射方向
[SerializeField] private float swordGravity;//劍的重力改變
2.實現劍的投擲(劍預制體的創建與代碼調用)
創建劍的對象,你可以創建一個父對象和子對象來表示一把劍,子對象負責掛載動畫組件,父對象負責掛載剛體碰撞器等。
為其添加旋轉和待機動畫,并添加rotation參數用來控制動畫
Skill腳本:
? ? protected Player player { get; private set; }//實例化Player,方便調用
? ? protected virtual void Start()
{
player = PlayerManage.instance.player;
}
為劍預制體添加Sword_Skill_Control腳本:
? ? private Animator anim;
private Rigidbody2D rb;
private CircleCollider2D cd;
? ? private Player player;
? ? private void Awake()
{
anim = GetComponent<Animator>();
rb = GetComponent<Rigidbody2D>();?
cd = GetComponent<CircleCollider2D>();
}
? ? public void SetupSword(Vector2 _dir,float _gravityScale)//給生成的預制體一個力和重力的改變
{
rb.velocity = _dir;
rb.gravityScale = _gravityScale;
}
Sword_Skill腳本:
? ? public void CreateSword()
{
GameObject newSword = Instantiate(swordPrefab,player.transform.position,transform.rotation);在玩家位置創建劍對象
? ? ? ? Sword_Skill_Control newSkillScript =newSword.GetComponent<Sword_Skill_Control>();
? ? ? ? newSkillScript.SetupSword(lanchForce, swordGravity);
}
PlayerAniamtionTrigger腳本:
? ? private void ThrowSword()
{
SkillManage.instance.sword.CreateSword();
}//在玩家投擲動畫中選擇一幀添加事件來調用該函數
3.實現瞄準時方向點的生成
我們想要在玩家瞄準時隨著鼠標移動展示不同的飛行軌跡并最終讓劍沿著這條軌跡發射,這需要我們創建一個點的預制體,然后再游戲時生成很多個點,并套用公式讓這些點排列成軌跡。
實現最終方向跟隨鼠標:
Sword_Skill腳本:
private Vector2 finalDir;
? ? private Vector2 AnimDirection()
{
Vector2 playerPostion=player.transform.position;
Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 direction = mousePosition - playerPostion;//由玩家指向鼠標
? ? ? ? return direction;
}
? ? protected override void ?Update()
{
if(Input.GetKeyUp(KeyCode.Mouse1))
{
finalDir = new Vector2(AnimDirection().normalized.x *lanchForce.x,AnimDirection().y *lanchForce.y);//normalized是歸一化處理,你可以理解把向量壓縮為1,乘以我們的初始方向即最終方向
}
}
? ? public void CreateSword()
{
GameObject newSword = Instantiate(swordPrefab,player.transform.position,transform.rotation);
? ? ? ? Sword_Skill_Control newSkillScript =newSword.GetComponent<Sword_Skill_Control>();
? ? ? ? newSkillScript.SetupSword(finalDir, swordGravity);//調用最終方向
}
實現瞄準點的排序:
? ? [Header("AnimDots info")]
[SerializeField] private int numbersofDots;//生成點的數量
[SerializeField] private float spaceBetweenTwoDots;//每個點間隔的時間
[SerializeField] private GameObject dotPrefab;//點的預制體,自行創建,記得更改圖層為地面
[SerializeField] private Transform dotsParent;//自行在玩家下創建一個子對象,作為生成所有點的父對象
? ? private GameObject[] dots;//生成點的數組
? ? private void GenerateDots()//生成所有點
{
dots = new GameObject[numbersofDots];
for (int i = 0; i < numbersofDots; i++)
{
dots[i]=Instantiate(dotPrefab,player.transform.position,Quaternion.identity,dotsParent);
dots[i].SetActive(false);
}
}
? ? protected override void Start()//調用上述函數
{
base.Start();
? ? ? ? GenerateDots();
}
? ? public void DotsActove(bool _isActive)//設置點是否可見
{
for(int i = 0; i < dots.Length; i++)//循環
{
dots[i].SetActive(_isActive);
}
}
? ? private Vector2 DotsPosition(float t)//返回每個點的位置
{
Vector2 position = (Vector2)player.transform.position + new Vector2(AnimDirection().normalized.x * lanchForce.x, AnimDirection().y * lanchForce.y) * t
+ .5f * (Physics2D.gravity * swordGravity) * (t * t);
//位置 = 初始位置 + 初速度 × 時間 + 0.5 × 加速度 × 時間2
? ? ? ? return position;
}
? ? protected override void ?Update()
{
if(Input.GetKeyUp(KeyCode.Mouse1))
{
finalDir = new Vector2(AnimDirection().normalized.x *lanchForce.x,AnimDirection().y *lanchForce.y);
}
? ? ? ? if(Input.GetKey(KeyCode.Mouse1))//按住鼠標右鍵時時刻更新這些點的位置
{
for(int i = 0; i < dots.Length; i++)
{
dots[i].transform.position = DotsPosition(i * spaceBetweenTwoDots);
}
}
}
PlayerAimSwordState腳本:
? ? public override void Enter()
{
base.Enter();
? ? ? ? SkillManage.instance.sword.DotsActove(true);
}
? ? public override void Exit()
{
base.Exit();
? ? ? ? SkillManage.instance.sword.DotsActove(false);
}//進入瞄準時可見這些點,退出消失
演示: