Unity学习——射箭游戏
射箭游戏
游戏视频<https://www.bilibili.com/video/av71160101/>
游戏工程文件https://github.com/JennySRH/3DGame/tree/master/ShootTarget
上下左右控制箭移动,空格键发射
靶对象
靶对象共有5环,由5个圆柱体组成,射中最中心的环得分5,射中最外层环得分为1。每个圆柱体都添加了mesh collider
,勾选Convex
,并且勾选了is Trigger
作为触发器。
对于靶对象而言,它需要完成两种行为:
- 作为触发器,感知是否有箭射中其中的某一环。
- 作为model,包含每一环的分数。
Target
上将挂载两个脚本,一个是TargetData
,挂载到每一个环上,用来得到该环的分数;另一个是TargetTrigger
,用来检测哪一个环被触发。
/* TargetData.cs */
public class TargetData : MonoBehaviour
{// 挂载到Target上的每一环,用来返回该环对应的分数。public int GetScore(){string name = this.gameObject.name;int score = 6 - (name[0] - '0');return score;}
}
/*TargetTrigger.cs*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class TargetTrigger : MonoBehaviour
{// 当有箭射中某一环后触发void OnTriggerEnter(Collider arrow_head){//得到箭身Transform arrow = arrow_head.gameObject.transform.parent;if (arrow == null){return;}if (arrow.tag == "Arrow"){arrow_head.gameObject.SetActive(false);//箭身速度为0arrow.GetComponent<Rigidbody>().velocity = new Vector3(0, 0, 0);arrow.GetComponent<Rigidbody>().isKinematic = true;arrow.tag = "Hit";// 分数控制器int score = this.gameObject.gameObject.GetComponent<TargetData>().GetScore();Singleton<ScoreController>.Instance.AddScore(score);//Debug.Log(score);}}}
然后将所有的圆柱体放到一个空物体上,做成预制。
箭
每一个箭由head
和body
组成,head
装有collider
。
箭挂载了JoyStick
可以通过上下左右来控制方向,如果按下空格键将添加刚体Rigidbody
,然后交由相应的动作控制器进行控制。
/*JoyStick.cs*/using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class JoyStick : MonoBehaviour
{public float speedX = 1.0F;public float speedY = 1.0F;bool flag = true;// Update is called once per framevoid Update(){// 只有在射出前能移动if(flag){float translationY = Input.GetAxis("Vertical") * speedY;float translationX = Input.GetAxis("Horizontal") * speedX;translationY *= Time.deltaTime;translationX *= Time.deltaTime;// 限制移动的范围if (transform.position.x - translationX < 1.5 && transform.position.x - translationX > -1.5&& transform.position.y + translationY > -0.8 && transform.position.y + translationY < 0.8){transform.position = transform.position + new Vector3(-translationX, translationY, 0);}if (Input.GetButton("Jump")){// 如果空格下,则给箭增加刚体,使其能够进行物理学的运动this.gameObject.AddComponent<Rigidbody>();this.gameObject.GetComponent<Rigidbody>().useGravity = false;flag = false;}}}
}
风
风是由一系列透明的触发器组成的。
触发器们挂载了WindTrigger
用来检测是否有箭头触发,然后交由相应的动作控制器控制。
/*WindTrigger*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class WindTrigger : MonoBehaviour
{void OnTriggerEnter(Collider arrow_head){//得到箭身Transform arrow = arrow_head.gameObject.transform.parent;if (arrow == null){return;}if (arrow.tag == "Arrow"){arrow.GetComponent<CCAction>().Move();}}
}
风力大小和风向由WindController
生成,挂载到全局的空物体上,使用单例模式获得。
/*WindController.sc*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class WindController : MonoBehaviour
{private float time = 5;private float strength = 0.5f;private Vector3 direction = new Vector3(0.01f,0,0);// Update is called once per framevoid Update(){if(time > 0){time -= Time.deltaTime;}else{time = 5;strength = UnityEngine.Random.Range(0.5f, 0.7f);direction = new Vector3(UnityEngine.Random.Range(-0.02f, 0.02f), UnityEngine.Random.Range(-0.02f, 0.02f), 0);}}public float GetStrength(){return strength;}public Vector3 GetDirection(){return direction;}
}
场景控制器——FirstSceneController
由于本次作业依旧沿用了之前的MVC
框架,所以只展示重要部分代码。
FirstSceneController
挂载到空物体上,用来加载第一个场景(一共也只有一个场景)。
/*FirstSceneController.cs*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class FirstSceneController : MonoBehaviour, ISceneController
{// 靶对象public GameObject target;// 箭队列public Queue<GameObject> arrowQueue = new Queue<GameObject>();// 当前正在操控的箭public GameObject arrow;// 风public GameObject wind;public void LoadSource(){// 清除记分Singleton<ScoreController>.Instance.ClearScore();// 靶对象初始化if (target != null){Destroy(target);}target = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Target"));if(arrow != null){Singleton<ArrowFactory>.Instance.FreeArrow(arrow);}// 箭队列初始化while (arrowQueue.Count > 0){Singleton<ArrowFactory>.Instance.FreeArrow(arrowQueue.Dequeue());}arrowQueue.Clear();// 初始化一个箭对象arrow = Singleton<ArrowFactory>.Instance.GetArrow();arrowQueue.Enqueue(arrow);}// Start is called before the first frame updatevoid Start(){this.gameObject.AddComponent<ArrowFactory>();this.gameObject.AddComponent<ScoreController>();this.gameObject.AddComponent<IGUI>();this.gameObject.AddComponent<WindController>();wind = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>("Prefabs/Wind"));// 设置第一个场景控制器为当前场景控制器Director.GetInstance().CurrentSceneController = this;Director.GetInstance().CurrentSceneController.LoadSource();}// Update is called once per framevoid Update(){if(arrow.tag == "WaveEnd"){arrow = Singleton<ArrowFactory>.Instance.GetArrow();arrowQueue.Enqueue(arrow);}}
}
运动学控制器——CCAction (颤抖效果)
CCAction
挂载到每个Arrow
上,用来负责Arrow
射中靶对象后的抖动效果以及遇到风之后产生的偏移效果。
/*CCAction.cs*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CCAction : MonoBehaviour, IAction
{private float time = 1;float radian = 0;float radius = 0.01f; Vector3 initPosition;public void Move(){Move(Singleton<WindController>.Instance.GetDirection(), Singleton<WindController>.Instance.GetStrength());}public void Move(Vector3 direction, float strength){this.transform.position += direction * strength;}// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){if(time > 0){if (this.gameObject.tag == "Hit"){time -= Time.deltaTime;// 弧度每次增加radian += 0.05f;// 颤抖float dy = Mathf.Cos(radian) * radius;transform.position = initPosition + new Vector3(0, dy, 0);}else{initPosition = transform.position;}}if(time <= 0){this.gameObject.tag = "WaveEnd";transform.position = initPosition;}}
}
动力学控制器——PhysicalAction
PhysicalAction
也挂载到Arrow
对象上,用来控制Arrow
发射的运动效果。
/*PhysicalAction.cs*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PhysicalAction : MonoBehaviour, IAction
{float force = 3;public void Move(){}public void Move(float force){this.force = force;}// Update is called once per framevoid Update(){// 如果没有射中靶对象if(this.gameObject.transform.position.z < -1){this.gameObject.tag = "WaveEnd";}}void FixedUpdate(){// 如果射中了靶对象if (this.gameObject.GetComponent<Rigidbody>() != null){this.gameObject.GetComponent<Rigidbody>().AddForce(new Vector3(0, 0, -1) * force);}}}
记分器——ScoreController
ScoreController
也是使用单例模式,作为全局唯一来记录分数。
![demo](../ShootTarget/demo.gifusing System.Collections;
using System.Collections.Generic;
using UnityEngine;public class ScoreController : MonoBehaviour
{private int score;public void ClearScore(){score = 0;}public void AddScore(int score){this.score += score;}public int GetScore(){return this.score;}}
效果展示
改进打飞碟游戏
增加一个运动的接口类ActionManager
,物理运动PhysicalAction
和运动学变换CCAction
都将实现该接口。
public interface IActionManager
{void Move(Vector3 direction, float speed);
}
CCAction
public class CCAction : MonoBehaviour, IActionManager
{public Vector3 direction;public float speed;public void Move(Vector3 direction,float speed){this.direction = direction;this.speed = speed;}// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){this.gameObject.transform.position += speed * direction * Time.deltaTime;}
}
对于PhysicalManager
而言,Move
函数是与其功能不匹配的,但是我们又不想丢弃这个CCAction
和ActionManager
,所以我们可以通过adapter模式,进行适配。
PhysicalManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PhysicalManager : MonoBehaviour, IActionManager
{public float speed;public void Move(float speed){this.speed = speed;}public void Move(Vector3 direction, float speed){Move(speed);}void FixedUpdate(){Rigidbody rigid = this.gameObject.GetComponent<Rigidbody>();if(rigid){//Debug.Log(speed);rigid.AddForce(Vector3.down * speed);} }// Start is called before the first frame updatevoid Start(){this.gameObject.GetComponent<Rigidbody>().useGravity = false;}}
Unity学习——射箭游戏相关推荐
- Unity3D学习——射箭游戏(工厂模式)
成品展示 每两秒会获得一个稳定风速,玩家可以把握住这个瞬间射箭,击中不同环得分不同,不击中不扣分,60s内够100分则获胜 游戏制作 脚本挂载与预制 箭靶子预制 在一个空对象上挂载五个扁平同心圆柱,设 ...
- Unity学习之游戏初步策划
欢迎大家来到我的博客http://unity.gopedu.com/home.php?mod=space&uid=3352&do=blog&view=me&from=s ...
- 面向完全初学者的Unity和C#游戏开发学习教程
了解如何通过使用Unity游戏引擎和C#制作BomberMan风格的3D游戏来制作您的第一款视频游戏 你会学到: 使用Unity 2021学习3D游戏开发 通过制作你的第一个3D游戏来学习C#编程语言 ...
- C#和Unity编码和游戏开发学习教程
MP4 |视频:h264,1280×720 |音频:AAC,44.1 KHz,2 Ch 语言:英语+中英文字幕(根据原英文字幕机译更准确) |时长:110节课(26小时25分钟)|大小解压后:18.6 ...
- Unity优化手机游戏学习教程
流派:电子学习| MP4 |视频:h264,1280×720 |音频:AAC,48.0 KHz 语言:英语+中英文字幕(根据原英文字幕机译更准确)|大小解压后:3.69 GB |时长:6h 44m 创 ...
- Unity学习笔记1 简易2D横版RPG游戏制作(一)
这个教程是参考一个YouTube上面的教程做的,原作者的教程做得比较简单,我先参考着做一遍,毕竟我也只是个初学者,还没办法完全自制哈哈.不过我之前也看过一个2D平台游戏的系列教程了,以后会整合起来,做 ...
- [Unity 学习] Unity 入门学习及第一个游戏
[Unity 学习] Unity 入门学习及第一个游戏 跟着教程做的一个小游戏,基本上说就算我这样的零基础,两个小时就能实现. 主要就是熟悉一下 C#和 Unity,做一个能跑的东西. 简单的 Dem ...
- 【贪玩巴斯】Unity3D初学圣经(一)——学习要求 Unity简单介绍 游戏引擎介绍 课程体系介绍 「1-1 到 1-4 」—— 2021年12月9日
Unity3D初学圣经 一 --学习要求 & Unity简单介绍 & 游戏引擎介绍 & 课程体系介绍 本文对应视频P1 1-1 到P2 1-4 1.学习要求 2.Unity简单 ...
- Unity学习笔记—二次元日系游戏制作(实践篇-游戏初始化场景制作)
原教程:siki:二次元日系游戏制作工具 - live2dSDK入门教程 http://www.sikiedu.com/my/course/282 (上)Unity学习笔记-二次元日系游戏制作(理论篇 ...
最新文章
- 物联网安全:LED灯中存在多个安全漏洞
- com学习笔记(6)类厂
- WPF MvvmLight简单实例(1) 页面导航
- 10亿美元卖身!腾讯IDG投资的无人车独角兽Zoox,被曝归入贝佐斯麾下
- golang install/build 生成的文件命名和路径
- linux下svn重新定位的方法
- 如何利用多核CPU提高虚拟现实性能?
- Java并发-Fork/Join框架
- block的用法以及block和delegate的比较(转发)
- Class Imbalance Problem
- error while loading shared libraries: xxx.so.x 错误的原因和解决办法
- tf.reshape()
- Chrome浏览其中,关闭窗口js无效.(window.close())
- spark配置IntelliJ开发环境详解
- Winform微信扫码支付
- HTML5前端基础知识
- 计算机网络和internet选项,详细教你电脑ie的internet选项在哪
- VC++ 在任务栏图标上显示进度条效果
- 淘宝如何做到懂你的推荐的?揭秘千人千面个性化推荐原理!
- firefly的RK3399AIOC开发板+海康工业相机抓图预览
热门文章
- 理光复印机扫描到windows共享文件夹操作步骤
- [BUAA OO Unit 3 HW12] 第三单元总结
- LeetCode短视频 | 最长有效括号使用栈很容易解决,但偏用动态规划
- 【LaTex】beamer中插入GIF动画
- python切片-截取-逆序截取
- 【PTA-A】1091 Acute Stroke (30 分)(BFS、队列)
- 【Linux】U盘安装Ubuntu 18.04之启动盘制作工具选择
- 鸿蒙充值卡是不是真的,手机充值卡怎么变现
- mysql UNION ALL查询分页
- 设置Windows 7锁屏背景图片