首页 > 代码库 > 自制Unity小游戏TankHero-2D(3)开始玩起来
自制Unity小游戏TankHero-2D(3)开始玩起来
自制Unity小游戏TankHero-2D(3)开始玩起来
我在做这样一个坦克游戏,是仿照(http://game.kid.qq.com/a/20140221/028931.htm)这个游戏制作的。仅为学习Unity之用。图片大部分是自己画的,少数是从网上搜来的。您可以到我的github页面(https://github.com/bitzhuwei/TankHero-2D)上得到工程源码。
本篇主要记录金币、按钮、坦克工厂、小地图等小部件,让整个场景初步成为一个可玩的游戏。
在本篇在制作过程中,修改了前两篇的很多东西,算是对Unity更加熟悉了。
金币
玩家击毁一个敌方坦克,会敌方坦克所在位置会出现1个金币。金币可以用来升级玩家坦克的速度、武器等,也可以用来恢复生命。
金币有3个脚本。
Show Up控制金币的出现是从透明到全不透明的。
1 public class ShowUp : MonoBehaviour { 2 3 public float showUpSpeed = 1; 4 private SpriteRenderer spriteRenderer; 5 6 void Awake() 7 { 8 this.spriteRenderer = this.GetComponent<SpriteRenderer>(); 9 var color = this.spriteRenderer.color;10 this.spriteRenderer.color = new Color(color.r, color.g, color.b, 0);11 }12 13 // Update is called once per frame14 void Update () {15 if (this.spriteRenderer == null) { return; }16 17 this.spriteRenderer.color = Color.Lerp(this.spriteRenderer.color, Color.white, this.showUpSpeed * Time.deltaTime);18 19 //Debug.Log(string.Format("A: {0}", this.spriteRenderer.color.a));20 if (Mathf.Abs(Color.white.a - this.spriteRenderer.color.a) <= 0.02f)21 {22 this.spriteRenderer.color = Color.white;23 this.spriteRenderer = null;24 }25 }
Coin Info保存金币的价值。
注意:脚本中要保留一个Start或一个Update函数,否则在Inspector面板就不会显示脚本组件前面的勾选框了。
1 public class CoinInfo : MonoBehaviour {2 3 public int value;4 5 void Start()6 {7 }8 9 }
Picked Coin让金币碰到玩家坦克时销毁自己。
1 public class PickedCoin : MonoBehaviour { 2 3 private bool picked; 4 5 void Awake() 6 { 7 this.picked = false; 8 } 9 10 void Start () {11 12 }13 14 void OnTriggerEnter2D(Collider2D other)15 {16 if (other.tag != Tags.hero) { return; }17 18 if (!this.picked)19 {20 this.picked = true;21 MonoBehaviour.Destroy(this.gameObject);22 }23 }24 }
游戏暂停和继续
用一个按钮来控制游戏的暂停和继续。
选择UI-Button即可添加一个按钮。
在按钮的Button组件中,添加一个On Click(),将含有响应点击事件的脚本赋给它,选择对应的事件函数即可。
那么事件函数怎么写呢?
游戏暂停的原理很简单,只需 Time.timeScale = 0; ,那么今后所有的 Time.deltaTime 都将是0。因此所有乘以 Time.deltaTime 的地方都不会再有进展。
1 private float originalTimeScale; 2 private UnityEngine.UI.Text buttonText; 3 4 void Awake() 5 { 6 this.originalTimeScale = Time.timeScale; 7 this.buttonText = this.GetComponentInChildren<UnityEngine.UI.Text>(); 8 } 9 10 public void btnPause_Click()11 {12 if (Time.timeScale > 0)13 {14 Time.timeScale = 0;15 buttonText.text = "Continue";16 }17 else18 {19 Time.timeScale = this.originalTimeScale;20 buttonText.text = "Pause";21 }22 }
在激烈的游戏过程中,把鼠标挪到屏幕某处点击按钮是很费劲的。所以,添加一个按下Space键就可以暂停或继续游戏的功能很有必要。只需将刚刚的btnPause脚本赋给btnPause对象,并添加如下代码。
1 void Update () {2 if (Input.GetKeyDown(KeyCode.Space))3 {4 btnPause_Click();5 }6 }
要注意的是,只要在OnClick()中设置好,按钮就能用了。将脚本btnPause作为组件添加到按钮是不必要的。我是为了方便地实现按下Space键也能激发按钮事件才这么做的。
坦克工厂
现在可以在界面上方三个点产生敌方坦克。后续我将此处改造为关卡控制器。此处暂时没什么可说的。
小地图
整个游戏地图有的大,一屏显示不完,所以给个能显示全地图的小地图是很好的。
制作小地图的原理是再添加一个摄像机smallMap,确保其Depth大于主摄像机。这样小地图就会显示在主场景上层。调整smallMap的Viewport属性,使其只在界面的某个角落显示。这里我让小地图显示在场景左下角,其长宽均为场景的五分之一即0.2。
注意,Viewport的X、Y、Width、Height属性都是0~1的,表示的是百分比。
注意,上图左上方红色围起来的白色框,其长宽比=下方Game视图的长宽比,后面我就是根据这个调整小地图的长宽的。
完成后,在Game视图里是这样的,小地图并不是正方形。这不好。
不过这个问题我用脚本解决了,实际上是调整了摄像机的Viewport的长宽属性,使之调整到相同的长度。
脚本如下。思路是,当场景的width大于height时,要缩小小地图的width;当场景的width小于height时,要缩小小地图的height。
1 public class AdjustViewPort : MonoBehaviour { 2 3 Camera cameraComponent; 4 private float screenWidth; 5 private float screenHeight; 6 private Rect originalCameraRect; 7 8 void Awake() 9 {10 this.cameraComponent = this.GetComponent<Camera>();11 this.originalCameraRect = this.cameraComponent.rect;12 }13 14 void Update () {15 var width = Screen.width;16 var height = Screen.height;17 if (width == this.screenWidth && height == this.screenHeight) { return; }18 19 this.screenWidth = width;20 this.screenHeight = height;21 22 if (width > height)23 {24 var rect = this.cameraComponent.rect;25 rect.width = this.originalCameraRect.width * ((float)height / (float)width);26 this.cameraComponent.rect = rect;27 }28 else29 {30 var rect = this.cameraComponent.rect;31 rect.height = this.originalCameraRect.height * ((float)width / (float)height);32 this.cameraComponent.rect = rect;33 }34 }35 }
只显示小地图的话,可能会跟场景混淆,所以给小地图加个红色的边框,就区分得明显了。我搜了很多加边框的方法,发现都太繁琐,还要依赖各种包、库。还是直接画一个Texture简单。
为方便起见,就在刚刚的AdjustViewPort脚本中同时绘制边框好了。
所需的边框纹理就是一个内部透明四周为红色的PNG图片。
(下面的脚本忽略了调整长宽相关的部分。)
1 public class AdjustViewPort : MonoBehaviour { 2 3 Camera cameraComponent; 4 public Texture borderTexture; 5 6 void Awake() 7 { 8 this.cameraComponent = this.GetComponent<Camera>(); 9 }10 11 void OnGUI()12 {13 var rect = this.cameraComponent.rect;14 float left = 0;15 float top = Screen.height - Screen.height * rect.height;16 float width = Screen.width * rect.width;17 float height = Screen.height * rect.height;18 19 GUI.DrawTexture(new Rect(left, top, width, height), this.borderTexture, ScaleMode.StretchToFill);20 }21 }
总结
本篇添加了一些虽小但用起来很方便的小部件。现在这个TankHero就算是可以玩了。下面我将设计实现关卡,让这个游戏具有多个关卡,并且可配置。
您可以到我的github页面(https://github.com/bitzhuwei/TankHero-2D)上得到工程源码。
请多多指教~
自制Unity小游戏TankHero-2D(3)开始玩起来