unity OnCollisionEnter2Dunity打开没反应应 Roguelike拾荒者

他的最新文章
他的热门文章
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)Unity2D游戏开发2D Roguelike拾荒者
726 || this.offsetHeight>700){if(this.offsetWidth/726 > this.offsetHeight/700){this.width=726;}else{this.height=700;}}" style="max-width:726max-height:700" title="点击查看原图" onclick="if(this.parentNode.tagName!='A') window.open('http://www.ceeger.com/forum/attachment/1602/thread/7_97895_fbe6f2d1126729a.jpg');" />
最新的课程出来了《拾荒者》,这个课程一共22个课时,教你学习Unity2D游戏开发,这个课程也是根据Unity5.2来开发的哦!里面的代码量比坦克大战要多一些,大家要慢慢研究学习!马上春节快到了,祝福大家新年快乐哦!
课时列表:01-游戏介绍02-创建游戏工程,素材介绍03-创建游戏主角04-创建敌人1号和2号的Prefab05-创建游戏的其他元素地板,围墙,墙和食物06-创建地图管理器-用于地图生成07-控制障碍物的生成08-完成敌人和食物的随机生成09-代码优化10-完善主角和敌人的动画状态机11-控制主角的移动12-控制主角对墙体的攻击13-控制主角吃食物14-控制敌人的移动15-奔跑吧,僵尸16-控制敌人的攻击17-控制游戏食物数量UI的显示18-控制游戏的失败19-游戏关卡的胜利判断20-完成关卡的加载21-控制天数UI的显示22-给游戏添加音效《游戏结束》
百度网盘下载地址:
其他课程:Tanks坦克大战视频教程 公众号内回复119DOTween动画插件视频教程 & &公众号内回复118游戏编程进阶篇 第二季 Windows游戏开发 公众号内回复112Unity5.2入门课程 - 进入Unity开发的奇幻世界 公众号内回复109C#编程课程 公众号内回复102、103、104、105游戏中广告SDK接入课程 公众号内回复 106、107游戏中支付SDK接入课程 公众号内回复108Unity游戏开发学习路线 & &公众号内回复100
请关注siki的微信公众号 devsiki 接收最新视频 开发资源和文章信息
726 || this.offsetHeight>700){if(this.offsetWidth/726 > this.offsetHeight/700){this.width=726;}else{this.height=700;}}" style="max-width:726max-height:700" onclick="if(this.parentNode.tagName!='A'&&this.width>screen.width-461) window.open(this.src);" />
要评论请先&或者&
nice!!!!!!!!!!!!!!!!!!!!
很不错啊 谢谢 !!!!
感谢楼主分享
感谢楼主分享!
我表示非常感谢!
感谢楼主分享!
顶贴,谢谢分享<option value='/video/av5480978/index_1.html' cid='、01.2D Roguelike 1 of 14 - Project Introduction
<option value='/video/av5480978/index_2.html' cid='、02.2D Roguelike 2 of 14 - Animations
<option value='/video/av5480978/index_3.html' cid='、03.2D Roguelike 3 of 14 - Tile Prefabs
<option value='/video/av5480978/index_4.html' cid='、04.2D Roguelike 4 of 14 - Board Manager
<option value='/video/av5480978/index_5.html' cid='、05.2D Roguelike 5 of 14 - Game Manager
<option value='/video/av5480978/index_6.html' cid='、06.2D Roguelike 6 of 14 - Moving Objects
<option value='/video/av5480978/index_7.html' cid='、07.2D Roguelike 7 of 14 - Walls
<option value='/video/av5480978/index_8.html' cid='、08.2D Roguelike 8 of 14 - Player Animator Controller
<option value='/video/av5480978/index_9.html' cid='、09.2D Roguelike 9 of 14 - Player Script
<option value='/video/av5480978/index_10.html' cid='、10.2D Roguelike 10 of 14 - Enemy Script
<option value='/video/av5480978/index_11.html' cid='、11.2D Roguelike 11 of 14 - Enemy Animator Controller
<option value='/video/av5480978/index_12.html' cid='、12.2D Roguelike 12 of 14 - UI & Levels
<option value='/video/av5480978/index_13.html' cid='、13.2D Roguelike 13 of 14 - Audio
<option value='/video/av5480978/index_14.html' cid='、14.2D Roguelike 14 of 14 - Mobile
视频地址复制
Flash地址复制
Html地址复制
离线看更方便
用或其他应用扫描二维码
Unity官方教程视频~
广播电视节目制作经营许可证:(沪)字第1248号
| 网络文化经营许可证:沪网文[6号 | 信息网络传播视听节目许可证:0910417 | 互联网ICP备案:沪ICP备号-3 沪ICP证:沪B2- | 违法不良信息举报邮箱: | 违法不良信息举报电话:转3
公司名称:上海宽娱数码科技有限公司 | 公司地址:上海市杨浦区政立路485号 | 客服电话:Unity 9 Unity2D游戏开发 Roguelike拾荒者
任务1:游戏介绍
Food:相当于血量:每走一步下降1,吃东西可以回复(果子10药水20),被怪物攻击会减少中间的障碍物可以打破,人走两步僵尸走一步;走到Exit进入下一关
最外圈的过道会保证是空的,其他的随机生成(--确保主角能够到达出口)
任务2:创建工程、素材
pan.baidu.com/s/1kTYS8ez
Unity5.2.1
2D Project -- Roguelike  导入Assets.unitypackage
Sprites-&所有切好的图片 -- 主角/地形/出口/围墙/僵尸等
任务3:创建游戏主角
Sprites中找到6个主角Scavengers的sprite图片,拖入Hierachy中  会自动在游戏物体Scavengers_SpritesSheet_0中创建一个动画Animator,并将Animation  和AnimationController保存在Sprites文件夹中,重命名控制器为Player/ 动画为PlayerIdle  并创建文件夹分类Assets-&Animations-&Animation/AnimatorController
此时,运行游戏,会自动播放Idle动画
双击AnimatorController打开动画编辑器,修改速度为0.5
创建攻击动画:  将两个攻击Sprites拖入Player物体,会自动在Player中创建一个新的动画PlayerAttack
创建受攻击动画:相似 -- PlayerUnderAttack
创建主角的Prefab
任务4:创建敌人
与创建主角相似
创建完Enemy1,创建Enemy1的Prefab
因为Enemy2的动画控制器AnimatorController与Enemy1相同  在Project视窗中右键Create-&Animator Override Controller  将Enemy1的Animator赋值给新建的Animator -- 表示两个Enemy共用一个状态机  将Hierarchy中的Enemy1-&GameObject-&Break prefab instance,重命名为Enemy2  将Enemy2 Animator赋值给Enemy2  创建Enemy2的两个动画,将动画拖入Enemy2 Animator赋值即可
相当于:Enemy1和Enemy2共用了Enemy1的状态机(Animator),但是使用了不同动画
创建Enemy2的Prefab
任务5:创建地板/ 围墙/ 食物
创建地板:
把8种地板和出口分别拖入,并重命名Floor1~8/ Exit
把8中障碍物拖入,重命名为Wall1~8
做成Prefab&
创建围墙:三种围墙,重命名为OutWall1~3并做成Prefab
创建食物:拖入Soda和Food,做成Prefab
任务6:生成地图
创建空物体GameManager
创建MapManager.cs  // 地图左下角设置为(0, 0)  public GameObject[] outWallArray/ floorA  // 创建根物体  private Transform mapH  mapHolder = new GameObject("Map").
  // 初始化围墙  for x for y(...) {    GameO    if (x==0 || y==0 || x==cols-1 || y==rows-1) {      int index = Random.Range(0, outWallArray.Length);      cell = GameObject.Instantiate        (outWallArray[index], ...(x, y, 0), Quaternion.identity) as GameO      // as GameObject -- .Instantiate()生成的为Object类型,强制转化为GameObject      // 在(x,y,0)处生成一个旋转为0的围墙    } else ...    cell.transform.SetParent(mapHolder);  }
  // 初始化地板  else {    int index = Random.Range(0, floorArray.Length);    cell = GameObject.Instantiate      (floorArray[index], ...(x,y,0), Quaternion.identity) as GameO  }
此时生成的地图并不位于相机正中心  -- 地图长10宽10 -- (每一格长宽为1,从(0,0)开始,即画面从(-0.5, -0.5开始))  --& Camera位置:(4.5, 4.5, 0),颜色改为黑色
private void InitMap() {
for (int x = <span style="color: #; x & x++) {
for (int y = <span style="color: #; y & y++) {
if (x == <span style="color: # || x == cols - <span style="color: # || y == <span style="color: # || y == rows - <span style="color: #) {
int index = Random.Range(<span style="color: #, outWallArray.Length);
cell = GameObject.Instantiate
(outWallArray[index], new Vector3(x, y, <span style="color: #), Quaternion.identity);
int index = Random.Range(<span style="color: #, floorArray.Length);
cell = GameObject.Instantiate
(floorArray[index], new Vector3(x, y, <span style="color: #), Quaternion.identity);
cell.transform.SetParent(mapHolder);
任务7:控制障碍物的生成
在InitMap()中
private List&Vector2& positionList = new List&Vector2&(); // 用于取得中间部分的格子位置
positionList.Clear();
for(int x/y = 0 + 2; x/y & cols/rows - 2; x/y++) {& // 围墙一列,空道一列  positionList.Add(new Vector2(x, y));}
// 从上面的positionList中随机取得格子放入障碍物/食物/敌人// 创建障碍物public GameObject[] wallArray;public int min/maxCountWall = 2/8;int wallCount = Random.Range(minCountWall, maxCountWall + 1);for(int i = 0~wallCount) {  // 随机取得格子位置  int positionIndex = Random.Range(0, positionList.Count); // 随机取得index  Vector2 pos = positionList[positionIndex]; // 得到位置信息  positionList.RemoveAt[positionIndex]; // 移除该位置 -- 保证一个格子只能有一个东西  // 随机取得障碍物  int wallIndex = Random.Range(0, wallArray.Length);  GameObject cell = GameObject(wallArray[...], pos, ...) as GameO  cell.transform.SetParent(mapHolder);}
避免地板将障碍物覆盖,设置Layer:Background/ Items/ Roles
positionList = new List&Vector2&();
positionList.Clear();
for(int x = <span style="color: #+<span style="color: #; x & cols - <span style="color: #; x++) {
for(int y = <span style="color: # + <span style="color: #; y & rows - <span style="color: #; y++) {
positionList.Add(new Vector2(x, y));
int wallCount = Random.Range(minCountWall, maxCountWall + <span style="color: #);
for(int i = <span style="color: #; i & wallC i++) {
int positionIndex = Random.Range(<span style="color: #, positionList.Count);
Vector2 pos = positionList[positionIndex];
positionList.RemoveAt(positionIndex);
int wallIndex = Random.Range(<span style="color: #, wallArray.Length);
GameObject cell = GameObject.Instantiate
(wallArray[wallIndex], pos, Quaternion.identity) as GameO
cell.transform.SetParent(mapHolder);
任务8&9:敌人和食物的随机生成 & 代码优化
食物和敌人的数量与关卡有关 -- 数量成正比
创建GameManager.cs -- 控制游戏关卡  public int level = 1;
在MapManager.cs中  // 获取GameManager  private GameManager gameM  gameManager = GetComponent&GameManager&();
创建食物 -- 数量2~level*2  int foodCount = Random.Range(2, gameManager.level * 2 + 1);  // 取得随机位置 -- 重复代码写成Vector2 RandomPosition()  Vector2 pos = RandomPosition();  // 随机取得物体 -- 重复代码写成GameObject RandomPrefab(GameObject[] prefabs);  GameObject foodPrefab= Instantiate(RandomPrefab(foodArray)) as GameO  foodPrefab.transform.setParent(mapHolder);
// get a random available position
private Vector2 RandomPosition() {
int positionIndex = Random.Range(<span style="color: #, positionList.Count);
Vector2 pos = positionList[positionIndex];
positionList.RemoveAt(positionIndex);
// get a random gameobject
private GameObject RandomPrefab(GameObject[] prefabs) {
int index = Random.Range(<span style="color: #, prefabs.Length);
return prefabs[index];
创建敌人 -- 数量为level / 2  int enemyCount = gameManager.level/2;  for(0~enemyCount) {    Vector2 pos = ...;    GameObject enemyPrefab = GameObject.Instantiate(...) as GameO    enemyPrefab.transform.setParent(mapHolder);  }
创建出口 -- 位置固定在右上方  GameObject exit =     (Instantiate(exitPrefab, new Vector2(cols-2, rows-2), Quaternion.identity) as GameO  exti.transform.SetParent(mapHolder);
-- 代码优化
上面的创建代码是可重用的 -- 写成method
private void InstantiateItems(int count, GameObject[] itemArray) {
for(int i = <span style="color: #; i & i++) {
GameObject item = GameObject.Instantiate(RandomPrefab
(itemArray), RandomPosition(), Quaternion.identity) as GameO
item.transform.SetParent(mapHolder);
任务10:完善主角和敌人的动画状态机
Player的动画:PlayerIdle/ PlayerUnderAttack/ PlayerAttack
PlayerIdle&--&PlayerUnderAttackPlayerIdle&--&PlayerAttack
在Animator中添加触发器Trigger分别称为Damage和Attack
Idle-&Attack/UnderAttack:  将Has Exit Time取消勾选 -- 在Idle动画的任何时候都可以随时切换到另一个动画  Transition Duration = 0 -- 因为这里的动画是帧动画,因此可以进行瞬时切换成其他动画  Conditions 切换方式:添加Attack/Damage Trigger
拖动左边的箭头可以手动播放动画;拖动右边的两个箭头可以手动控制何时切换
Attack/UnderAttack-&Idle:  勾选Has Exit Time即可 -- 播放完Attack/UnderAttack后自动切换到Idle动画  Transition Duration = 0 -- 瞬时间切换  Exit Time = 1 -- 退出时间(多久进行切换)
Enemy的动画:EnemyIdle/ EnemyAttack
Idle-&Attack:  添加触发器Attack  Has Exit Time uncheck  Transition Duration = 0
Attack-&Idle:  Has Exit Time check  Exit Time = 1  Transistion Duration = 0
检测动画:
运行游戏;选中Player/ Enemy;在Animator视窗中查看状态机
点击Trigger右边的小圆点,即为触发该Trigger
任务11:控制主角的运动
为Player添加刚体,用于控制移动,勾选Is Kinematic
为Player添加BoxCollider2D,用于检测碰撞(大小不能设置为(1,1),0.9就好)
为Player添加Player.cs来控制移动  private int posx/posy = 1; // 当前位置  private int Vector2 targetPos = new Vector2(1,1); // 目标位置
  float h/v = Input.GetAxisRaw("Horizontal"/"Vertical"); // GetAxisRaw()的返回值为-1/0/1  targetPos += new Vector2(h,v); // 按键后,目标位置发生改变  private Rigidbody2D rigidbody = GetComponent&Rigidbody2D&(); // 得到刚体,用于移动  rigidbody.MovePosition(Vector2.Lerp(transform.position, targetPos, smoothing*Time.deltaTime));     // MovePosition(目标位置):向目标位置移动    // Lerp(起点,终点,速度);这里设smoothing=1
发现此时按下按钮会移动很长的距离 -- Update中不停调用targetPos += Vector2();&
需要设置一个休息时间:  public float restTime = 0.5f;  public float restTimer = 0.5f; // 计时器
在Update()中  restTimer += Time.deltaT // 每次增加时间间隔  if(restTimer &= restTime) { // 还在休息间隔中     // 不进行其他操作  }
  当有按键按下时:  if(h!=0 || v!=0) {    targetPos += ...; // 更新目标位置    rigidbody.MovePosition(...); // 移动    restTimer = 0; // 重置计时器  }
按下按键时,只能移动一点点距离  将rigidbody.MovePosition()代码移出if条件  因为每一帧都需要调用而不是只有按键的时候调用
发现可以一次同时在水平和竖直移动 -- 和游戏规则有悖  if(h!=0) v=0; // 优先控制竖直方向
void Update () {
rigidbody.MovePosition(Vector2.Lerp(transform.position, targetPos, smooth * Time.deltaTime));
if (restTimer & restTime) {
restTimer += Time.deltaT
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
if (h != <span style="color: #) {
v = <span style="color: #;
if (h != <span style="color: # || v != <span style="color: #) {
// 有按键输入时
targetPos += new Vector2(h, v);
restTimer = <span style="color: #; // 计时器归零
任务12:控制主角对墙体的攻击
给outWall添加BoxCollider2D,scale=0.9;添加tag = OutWall
给wall添加BoxCollider2D,scale=0.9;添加tag = Wall
在每次按键的时候,进行碰撞检测:  RaycastHit2D hit = Physics2D.Linecast(targetPos, targetPos + new Vector2(h, v));     // Physics2D.Linecast(起点,终点) 从起点向终点发射射线做检测,返回RaycastHit2D  if(hit.transform == null) { // 没有碰撞,可以行走  } else { // 有碰撞    switch(hit.collider.tag) {      case "OutWall": // 不做处理      case "Wall": // 进行攻击        // 向墙发送攻击的通知        // 在Wall里添加Wall.cs来处理行为 Wall.TakeDamage();        hit.collider.SendMessage("TakeDamage");
public int hp = <span style="color: #;
public Sprite damageS // 受损后的墙体图片
public void TakeDamage() {
hp -= <span style="color: #;
GetComponent&SpriteRenderer&().sprite = damageS
if(hp&=<span style="color: #) Destroy(this.gameObject);
禁用自身的collider,因为可能射线会碰到自身的collider:  private BoxCollider2D collider = GetComponent&...&();  collider.enabled =  ... // 射线检测  collider.enabled = // 检测后再启用
无论是移动还是攻击,都需要休息 -- 只要按下了按键,restTimer = 0;
攻击时,播放PlayerAttack动画  Player.cs    private Animator animator = GetComponent&Animator&();    animator.SetTrigger("Attack"); // 触发触发器
rigidbody.MovePosition(
Vector2.Lerp(transform.position, targetPos, smooth * Time.deltaTime));
if (restTimer & restTime) {
restTimer += Time.deltaT
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
if (h != <span style="color: #) {v = <span style="color: #;}
if (h != <span style="color: # || v != <span style="color: #) {
// 有按键输入时
collider.enabled = false; // 禁用自身collider
// 碰撞检测
RaycastHit2D hit =
Physics2D.Linecast(targetPos, targetPos + new Vector2(h, v));
if (hit.transform == null) {
// 没有检测到碰撞
targetPos += new Vector2(h, v);
// 检测到碰撞
switch (hit.collider.tag) {
case "OutWall":
case "Wall":
hit.collider.SendMessage("TakeDamage");
animator.SetTrigger("Attack");
restTimer = <span style="color: #; // 计时器归零
collider.enabled = true; // 检测完碰撞后 开启自身collider
任务13:控制主角吃食物
对食物进行碰撞检测:
对食物添加BoxCollider2D;设置为Is Trigger,scale=0.9,tag=food
存储当前食物 GameManager.public int food = 100;  将GameManager设置为单例模式
private static GameManager _
public static GameManager Instance {
private void Awake() {
_instance = this;
增加/减少食物的method:public void Add/ReduceFood(int count)  food +=/-=
case "Food":  // 用if判断hit.collider.name是Food(Clone)还是Soda(Clone)  GameManager.Instance.AddFood(10 | 20);  // 同时,需要移动Player位置 && 销毁食物  targetPos += new Vector2(h, v);  Destroy(hit.collider.gameObject);
case "Food":
targetPos += new Vector2(h, v);
Destroy(hit.collider.gameObject);
if (hit.collider.name == "Food(Clone)") {
GameManager.Instance.AddFood(<span style="color: #);
} else if(hit.collider.name == "Soda(Clone)") {
GameManager.Instance.AddFood(<span style="color: #);
任务14&15:控制敌人的移动
当Player移动两步时,敌人移动一步
给Enemy添加BoxCollider2D进行碰撞检测,size=0.9,&
给Enemy添加Rigidbody2D进行移动,勾选Is Kinematic:很重要  如果没有勾选,会导致后面Enemy被Player推走
给Enemy添加tag=Enemy
case "Enemy": // 说明所走的路径不通,判断失误,浪费一步  &
给Enemy添加Enemy.cs  Enemy是被动移动 -- 提供移动方法,供其他对象调用  public void Move() {    // 判断Player所在位置的方向    // Transform player = GameObject.FindGameObjectWithTag(...)&    Vector2 offset = player.position - transform.    if (offset.magnitude & 1.9f) { // 距离小于一格      // 攻击    } else { // 追 -- 哪个轴偏移大,就往哪里追      if (Mathf.Abs(offset.x) & Mathf.Abs(offset.y)) { // x轴移动        if(offset.x&0) x=-1; else x=1;      } else { // y轴移动        if(offset.y&0) y=-1;&else y=1;      }      targetPos += new Vector(x, y);    }
在GameManager.cs中统一管理游戏进程:  public List&Enemy& enemyList = new List...;
在Enemy.cs中:  GameManager.Instance.enemyList.Add(this);
在GameManager.cs中控制Enemy是否行走:  bool sleepStep = // 是否为休息状态  OnPlayerMove() {    if(sleepStep) sleepStep =    else { foreach enemy in enemyList { enemy.Move();       sleepStep = }  }
在Player.cs中  有按键按下的时候调用OnPlayerMove()  GameManager.Instance.OnPlayerMove();
此时,Enemy会随着主角移动而移动,但是Enmey没有碰撞检测
设置目标位置targetPos之前先做检测
// 更新位置之前,做碰撞检测
collider.enabled = false; // 否则会碰撞到自己的collider
RaycastHit2D hit = Physics2D.Linecast(targetPos, targetPos+new Vector2(x,y));
collider.enabled = true;
if (hit.collider == null) {
// 没有碰撞
targetPos += new Vector2(x, y);
switch (hit.collider.tag)
case "Wall":
case "OutWall": // 不可能出现外墙的情况
case "Food":
Destroy(hit.collider.gameObject);
targetPos += new Vector2(x, y);
任务16:控制敌人的攻击
private Animator animator = GetComponent&...&();animator.SetTrigger("Attack");player.SendMessage("TakeDamage", lossFood);& // 不同敌人的伤害不同
public void TakeDamage(int lossFood) {  GameManager.Instance.ReduceFood(lossFood);  animator.SetTrigger("UnderAttack");&}
任务17:控制游戏食物数量UI的显示
在Player每走一步就消耗一定量食物:  GameManager.Instance.ReduceFood(1);
在屏幕上显示食物:  右键创建UI-&Text,重命名FoodText  字体剧中,字号25,字体为Font-&PressStart2P-Regular,内容:Food: 100  放置在屏幕下方,Anchor Presets设置为bottom-center
在GameManager.cs中控制UI的更新  private Text foodT  在void Awake()中&加入 InitGame();    void InitGame() {       foodText = GameObject.Find("FoodText").GetComponent...;&       UpdateFoodText(0);    }
private void UpdateFoodText(int foodChange) {
if (foodChange == <span style="color: #) {
foodText.text = "Food: " +
} else if (foodChange & <span style="color: #) {
foodText.text = "+" + foodChange + "
foodText.text = foodChange + "
在ReduceFood()/ AddFood(){}&中加上 UpdateFoodText(count/-count);
任务18:控制游戏的失败  
游戏失败:Food &= 0;  Player每走完一步:检测food的数量  --&我的优化:在GameManager中的ReduceFood()中检测 --&没有必要每一步都检测
  if(food&=0){&    GameObject.FindGameObjectWithTag("Player").SetActive(false);&     //&显示游戏失败 -- UI-&Text,居中,白色,字号,字体,GameOver等等    gameOverText.enabled =  }
任务19&20:游戏关卡的胜利判断 && 下一关卡的加载
判断Player是否到达了Exit的位置(8,8)
每次Player移动,判断是否到达终点  Player每次移动,都会调用GameManager中的OnPlayerMove()  在OnPlayerMove()中加入    //&需要得到player的targetPos,与destinationPos比较    将targetPos改为[HideInInspector]public targetP    Player player = GameObject.Find...Tag(...).GetComponent...;    // 还需得到Exit的位置    MapManager mapManager = GetComponent...;    if(player.targetPos.x == mapManager.cols-2 && ...y==rows-2) {      private bool missionCompleted =      //&加载下一关卡      Application.LoadLevel(Application.loadedLevel); // 重新加载本关卡 --&已弃用      SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);&      // 需要记住某些值 -- 使用系统函数OnLevelWasLoaded()&    }
运行 -- 发现可以重置关卡了,但是所有数据会重置
GameManager实例不能销毁 -- 否则数据会重置  在GameManager.cs的Awake()中:
    DontDestroyOnLoad(gameObject);
运行 -- 发现原来的GameManager没有销毁,但是新建了另一个GameManager
不将GameManager放在场景中  --&将GameManager做成Prefab  -- 删除场景中的GameManager  在MainCamera中添加GameLoader.cs
// 实例化GameManager
public GameObject gameM
void Awake() {
if(GameManager.Instance == null) {
GameObject.Instantiate(gameManager);
任务21:控制天数UI的显示
当前天数的显示  UI-&Image-&DayI alt+上下左右居中;颜色设置为黑色  在DayImage中创建一个Text叫DayText;居中偏上;字号32;字体自定义;颜色白色
什么时候显示呢? -- 初始化UI的时候需要显示
GameManage.InitGame()中:  private Image dayImage = GameObject.Find("DayImage").GetComponent&Image&();  private Text dayText ...;  dayText.text = "Day " +
显示完天数,需要隐藏
void HideDayImage() {
dayImage.gameObject.SetActive(false);
在InitGame()最后调用 Invoke("HideDayImage", 1);&即可& --&过1s后调用
任务22:添加音效
GameManager.cs
阅读(...) 评论()

我要回帖

更多关于 unity打开没反应 的文章

 

随机推荐