【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili

- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public enum SwordType
- {
- Regular,
- Bounce,
- Pierce,
- Spin
- }
-
- public class Sword_Skill : Skill
- {
- public SwordType swordType = SwordType.Regular;//创建应一个enum列表,后面用来判断切换状态
-
- [Header("Bounce Info")]
- [SerializeField] private int bounceAmount;
- [SerializeField] private float bounceGravity;
-
- [Header("Pierce info")]
- [SerializeField] private int pierceAmount;
- [SerializeField] private float pierceGravity;
-
- [Header("Skill Info")]
- [SerializeField] private GameObject swordPrefab;//sword预制体
- [SerializeField] private Vector2 launchForce;//发射力度
- [SerializeField] private float swordGravity;//发射体的重力
-
- private Vector2 finalDir;//发射方向
-
- [Header("Aim dots")]
- [SerializeField] private int numberOfDots;//需要的点的数量
- [SerializeField] private float spaceBetweenDots;//相隔的距离
- [SerializeField] private GameObject dotPrefab;//dot预制体
- [SerializeField] private Transform dotsParent;//不是很懂
-
- private GameObject[] dots;//dot组
-
- protected override void Start()
- {
- base.Start();
-
- GenerateDots();//生成点函数
-
- SetupGravity();
- }
-
- private void SetupGravity()//每个剑的状态都对应了不同的剑重力
- {
- if(swordType == SwordType.Pierce)
- {
- swordGravity = pierceGravity;
- }
- if(swordType == SwordType.Bounce)
- {
- swordGravity = bounceGravity;
- }
- }
-
- protected override void Update()
- {
- base.Update();
- if (Input.GetKeyUp(KeyCode.Mouse1))
- {
- finalDir = new Vector2(AimDirection().normalized.x * launchForce.x, AimDirection().normalized.y * launchForce.y);
- //将位移量改为单位向量分别与力度的x,y相乘作为finalDir
- }
-
- if (Input.GetKey(KeyCode.Mouse1))
- {
- for (int i = 0; i < dots.Length; i++)
- {
- dots[i].transform.position = DotsPosition(i * spaceBetweenDots);//用循环为每个点以返回值赋值(传入值为每个点的顺序i*点间距
- }
- }
- }
- public void CreateSword()
- {
- GameObject newSword = Instantiate(swordPrefab, player.transform.position, transform.rotation);//创造实例,初始位置为此时player的位置
- Sword_Skill_Controller newSwordScript = newSword.GetComponent
();//获得Controller -
- if(swordType == SwordType.Bounce)
- {
- newSwordScript.SetupBounce(true, bounceAmount);
- }
- else if(swordType == SwordType.Pierce)
- {
- newSwordScript.SetupPierce(pierceAmount);
- }
-
-
-
- newSwordScript.SetupSword(finalDir, swordGravity, player);//调用Controller里的SetupSword函数,给予其速度和重力和player实例
-
- player.AssignNewSword(newSword);//调用在player中保存通过此方法创造出的sword实例
- DotsActive(false);//关闭点的显示
- }
- #region Aim region
- public Vector2 AimDirection()
- {
- Vector2 playerPosition = player.transform.position;//拿到玩家此时的位置
- Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);//https://docs.unity3d.com/cn/current/ScriptReference/Camera.ScreenToWorldPoint.html
- //大概就是返回屏幕上括号里的参数的位置,这里返回了鼠标的位置
- //拿到此时鼠标的位置
- Vector2 direction = mousePosition - playerPosition;//获得距离的绝对向量
-
- return direction;//返回距离向量
- }
-
- public void DotsActive(bool _isActive)
- {
- for (int i = 0; i < dots.Length; i++)
- {
- dots[i].SetActive(_isActive);//设置每个点是否显示函数
- }
- }
- private void GenerateDots()//生成点函数
- {
- dots = new GameObject[numberOfDots];//为dot赋予实例数量
- for (int i = 0; i < numberOfDots; i++)
- {
- dots[i] = Instantiate(dotPrefab, player.transform.position, Quaternion.identity, dotsParent);//对象与世界轴或父轴完全对齐
- //https://docs.unity3d.com/cn/current/ScriptReference/Quaternion-identity.html
- dots[i].SetActive(false);//关闭dot
- }
- }
-
- private Vector2 DotsPosition(float t)//传入顺序相关的点间距
- {
- Vector2 position = (Vector2)player.transform.position +
- new Vector2
- (AimDirection().normalized.x * launchForce.x,
- AimDirection().normalized.y * launchForce.y) * t //基本间距
- + .5f * (Physics2D.gravity * swordGravity) * (t * t)//重力影响
- ;
- //t是控制之间点间距的
- return position;//返回位置
- }//设置点间距函数
- #endregion
- }
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
-
- public class Sword_Skill_Controller : MonoBehaviour
- {
- [SerializeField] private float returnSpeed = 12;
- private bool isReturning;
-
- private Animator anim;
- private Rigidbody2D rb;
- private CircleCollider2D cd;
- private Player player;
-
- private bool canRotate = true;
- [Header("Piece info")]
- [SerializeField] float pierceAmount;
-
- [Header("Bounce info")]
- [SerializeField]private float bounceSpeed;//设置弹跳速度
- private bool isBouncing;//判断是否可以弹跳
- private int bounceAmount;//弹跳的次数
- public List
enemyTargets;//保存所有在剑范围内的敌人的列表 - private int targetIndex;//设置targetIndex作为敌人计数器
-
- private void Awake()
- {
- anim = GetComponentInChildren
(); - rb = GetComponent
(); - cd = GetComponent
(); - }
- public void ReturnSword()
- {
- rb.constraints = RigidbodyConstraints2D.FreezeAll;//修复剑只要不触碰到物体就无法收回的bug
- //rb.isKinematic = false;
- transform.parent = null;
- isReturning = true;
- }
- public void SetupSword(Vector2 _dir,float _gravityScale,Player _player)
- {
- player = _player;
- rb.velocity = _dir;
- rb.gravityScale = _gravityScale;
- if(pierceAmount < 0)
- anim.SetBool("Rotation", true); //其次在pierceAmount > 0时不启动旋转动画
- }
-
- public void SetupBounce(bool _isBouncing,int _bounceAmount)
- {
- isBouncing = _isBouncing;
- bounceAmount = _bounceAmount;
- }
-
- public void SetupPierce(int _pierceAomunt)
- {
- pierceAmount = _pierceAomunt;
- }
-
- private void Update()
- {
- if (canRotate)
- transform.right = rb.velocity;//使武器随着速度而改变朝向
-
- if (isReturning)
- {
- transform.position = Vector2.MoveTowards(transform.position, player.transform.position, returnSpeed * Time.deltaTime);//从原来的位置返回到player的位置
- //并且随着时间增加而增加速度
- if (Vector2.Distance(transform.position, player.transform.position) < 1)//当剑与player的距离小于一定距离,清除剑
- {
- player.CatchTheSword();
- }
- }
-
- BounceLogic();
- }
-
- private void BounceLogic()
- {
- if (isBouncing && enemyTargets.Count > 0)
- {
-
- transform.position = Vector2.MoveTowards(transform.position, enemyTargets[targetIndex].position, bounceSpeed * Time.deltaTime);
- //3.当可以弹跳且列表内数量大于0,调用ToWords,这将使剑能够跳到敌人身上
- if (Vector2.Distance(transform.position, enemyTargets[targetIndex].position) < .1f)
- {
- targetIndex++;
- bounceAmount--;//设置弹跳次数
- if (bounceAmount <= 0)
- {
- isBouncing = false;
- isReturning = true;
- }//这样会使当弹跳次数为0时,返回到角色手中
- if (targetIndex >= enemyTargets.Count)
- {
- targetIndex = 0;
- }
- }//利用与目标距离的判断,使剑接近目标距离时切换到下一个目标。
- //且如果所有目标都跳完了,切回第一个
- }
- }
-
- private void OnTriggerEnter2D(Collider2D collision)//传入碰到的物体的碰撞器
- {
- if (isReturning)
- {
- return;
- }//修复在返回时扔出时没有碰到任何物体,但返回时碰到了物体导致剑的一些性质发生改变的问题,及回来的时候调用了OnTriggerEnter2D
-
- collision.GetComponent
()?.Damage();//设置一下敌人受击动画 -
- if (collision.GetComponent
() != null)//首先得碰到敌人,只有碰到敌人才会跳 - {
- if (isBouncing && enemyTargets.Count <= 0)
- {
- Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 10);
- foreach (var hit in colliders)
- {
- if (hit.GetComponent
() != null) - {
- enemyTargets.Add(hit.transform);
- }
- }
- }
- }
-
- StuckInto(collision);
- }//打开IsTrigger时才可使用该函数
- //https://docs.unity3d.com/cn/current/ScriptReference/Collider2D.OnTriggerEnter2D.html
-
- private void StuckInto(Collider2D collision)
- {
- if(pierceAmount > 0 && collision.GetComponent
()!= null)//本质就是能穿过敌人,在amount>0时不执行能让剑卡在敌人里的语句就行 - {
- pierceAmount--;
- return;
- }
-
- canRotate = false;
- cd.enabled = false;//相当于关闭碰撞后触发函数。//https://docs.unity3d.com/cn/current/ScriptReference/Collision2D-enabled.html
-
- rb.isKinematic = true;//开启物理学反应 https://docs.unity3d.com/cn/current/ScriptReference/Rigidbody2D-isKinematic.html
- rb.constraints = RigidbodyConstraints2D.FreezeAll;//冻结所有移动
-
- if (isBouncing&&enemyTargets.Count>0)//修复剑卡不到墙上的bug
- return;
- //终止对动画的改变和终止附在敌人上
- transform.parent = collision.transform;//设置sword的父组件为碰撞到的物体
- anim.SetBool("Rotation", false);
- }
-
- }