官方示例Reguelike的学习笔记
# UnityPracticeProject
单例模式:
1 static public GameManager _instance = null; 2 void Awake () 3 { 4 if (_instance == null) 5 { 6 _instance = this; 7 } 8 else if (_instance != this) 9 { 10 Destroy(gameObject); 11 } 12 DontDestroyOnLoad(gameObject); 13 }
为player和enemy抽象一个基类来实现移动
1 public abstract class MoveObject : MonoBehaviour { 2 3 //start为虚函数,以便在子类中能重写 4 protected virtual void Start () 5 { 6 boxCollier = GetComponent<BoxCollider2D>(); 7 rb2D = GetComponent<Rigidbody2D>(); 8 inverseMoveTime = 1f / moveTime; 9 } 10 11 protected IEnumerator SmoothMovement(Vector3 end) 12 { 13 float sqrRemainingDistance = (transform.position - end).sqrMagnitude; 14 15 while(sqrRemainingDistance > float.Epsilon) 16 { 17 Vector3 newPosition = Vector3.MoveTowards(rb2D.position, end, inverseMoveTime * Time.deltaTime); 18 rb2D.MovePosition(newPosition); 19 sqrRemainingDistance = (transform.position - end).sqrMagnitude; 20 yield return null; 21 } 22 } 23 24 protected bool Move(int xDir, int yDir, out RaycastHit2D hit) 25 { 26 Vector2 start = transform.position; 27 Vector2 end = start + new Vector2(xDir, yDir); 28 boxCollier.enabled = false; 29 hit = Physics2D.Linecast(start, end, blockingLayer); //进行碰撞检测 30 boxCollier.enabled = true; 31 if (hit.transform == null) 32 { 33 StartCoroutine(SmoothMovement(end)); 34 return true; 35 } 36 return false; 37 } 38 39 //泛型virtual函数在基类中必须有实现体 40 protected virtual void AttemptMove<T>(int xDir, int yDir) 41 where T : Component 42 { 43 RaycastHit2D hit; 44 bool canMove = Move(xDir, yDir, out hit); 45 if (hit.transform == null) 46 return; 47 T hitComponent = hit.transform.GetComponent<T>(); 48 if (!canMove && hitComponent != null) 49 OnCantMove(hitComponent); 50 } 51 52 //泛型abstract函数只能在子类中实现 53 protected abstract void OnCantMove<T>(T component) 54 where T : Component;
场景加载
1 if(collision.tag == "Exit") 2 { 3 Invoke("Restart", restartLevelDelay); //调用重启函数 4 enabled = false; 5 } 6 7 private void Restart() 8 { 9 SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex, LoadSceneMode.Single); //触发场景加载事件 10 } 11 12 GameManager类: 13 void OnEnable() 14 { 15 SceneManager.sceneLoaded += OnSceneLoaded; 16 } 17 18 void OnSceneLoaded(Scene scene, LoadSceneMode mode) 19 { 20 InitGame(); 21 level++; 22 }
地图创建
1 private List<Vector3> gridPositions = new List<Vector3>(); 2 void InitialiseList() 3 { 4 gridPositions.Clear(); 5 for (int x = 1; x < col; x++) 6 { 7 for (int y = 1; y < row; y++) 8 { 9 gridPositions.Add(new Vector3(x, y, 0f)); 10 } 11 } 12 } 13 14 Vector3 RandomPosition() 15 { 16 int randomIndex = Random.Range(0, gridPositions.Count - 1); //最后一个格子用来放置过关图标 17 Vector3 randomPosition = gridPositions[randomIndex]; 18 gridPositions.RemoveAt(randomIndex); //把随机的格子移除,保证下次随机位置不会重复 19 return randomPosition; 20 }
遇到的问题:Exit对象OnTriggerEnter多次触发!
原因:在场景初始化的时候,由于刚开始测试时新建了一个地图一关卡,忘了删除,导致后来程序运行的时候创建了两遍场景(由于位置重叠没有发现),所以在同一个Exit位置,实际上有两个Exit对象,也就触发了两次OnTriggerEnter()函数,导致进入下一关的时候Food直接被清零了。
浙公网安备 33010602011771号