屏幕坐标和世界坐标的转换+对象池技术(3D打地鼠小游戏)
2015-10-08 22:21
302 查看
游戏中可能经常会遇到需要某个物体跟着鼠标移动,然后又需要把物体放在某个鼠标指定的位置
实现方式
Camera.main.WorldToScreenPoint
Camera.main.ScreenToWorldPoint
3D打地鼠实例
我这里用到的素材都比较简陋,几乎全是用Unity做的
首先是锤子
就是两个Cylinder,在把手的位置放一个空物体用于模拟锤子的动作,命名为Hammer,把锤子作为Hammer的子物体,给Hammer添加Animation动画:
在三个关键帧位置设置Hammer的Rotation,分布为(45, 0, 0),(-15, 0, 0),(45, 0, 0)
把锤子头部的Tag改为Hammer,并添加刚体,勾选UseGravity和IsKinematic,用于触发打到地鼠事件
然后是地鼠
这里就用Capsule代替了
然后给Capsule添加Animation动画,并放在一个空物体上,命名为Mouse,更改Tag为Mouse
为Capsule添加脚本
在四个关键帧位置设置Capsule的Position分别为(0, -1, 0),(0, 0, 0),(0, 0, 0),(0, -1, 0)
将Mouse拖为预设体
锤子的动画状态机:
布置洞口
为了能看到地鼠的出没,我这里用PS简单的做了一张有有透明洞口的png图片:
<=这里有一张看不见的图片。。。
新建一个Material,将Shader该为Transparent/Diffuse,把上面那张图片拖上去
新建9个Cube,把刚才新建的Material赋予它,改变位置和大小,调整摄像机,最终结果如下:
下面是锤子上的代码:
最后是对象池的代码:
好了,游戏基本完成
网页版预览
PC版下载
实现方式
Camera.main.WorldToScreenPoint
Camera.main.ScreenToWorldPoint
3D打地鼠实例
我这里用到的素材都比较简陋,几乎全是用Unity做的
首先是锤子
就是两个Cylinder,在把手的位置放一个空物体用于模拟锤子的动作,命名为Hammer,把锤子作为Hammer的子物体,给Hammer添加Animation动画:
在三个关键帧位置设置Hammer的Rotation,分布为(45, 0, 0),(-15, 0, 0),(45, 0, 0)
把锤子头部的Tag改为Hammer,并添加刚体,勾选UseGravity和IsKinematic,用于触发打到地鼠事件
然后是地鼠
这里就用Capsule代替了
然后给Capsule添加Animation动画,并放在一个空物体上,命名为Mouse,更改Tag为Mouse
为Capsule添加脚本
public class MouseController : MonoBehaviour { /// <summary> /// Recycles the mouse. /// </summary> public void RecycleMouse() { // Destroy(transform.parent.gameObject); //对象池回收. MousePool.Instance.RecycleMouse(transform.parent.gameObject); } //被打到时的触发方法. void OnTriggerEnter(Collider other) { if(other.tag == "Hammer") { print("Score"); RecycleMouse(); } } }
在四个关键帧位置设置Capsule的Position分别为(0, -1, 0),(0, 0, 0),(0, 0, 0),(0, -1, 0)
将Mouse拖为预设体
锤子的动画状态机:
布置洞口
为了能看到地鼠的出没,我这里用PS简单的做了一张有有透明洞口的png图片:
<=这里有一张看不见的图片。。。
新建一个Material,将Shader该为Transparent/Diffuse,把上面那张图片拖上去
新建9个Cube,把刚才新建的Material赋予它,改变位置和大小,调整摄像机,最终结果如下:
下面是锤子上的代码:
public class HammerController : MonoBehaviour { Animator anim; Transform head; void Start () { anim = this.GetComponent<Animator>(); head = GameObject.Find("Head").transform; } Vector3 newPosition; Vector3 screenPos; void Update () { MouseShow(); HammerMove(); } //记时器. float timer = 0; //地鼠的预设体. public GameObject mousePrefab; int ranIndexX; int ranIndexY; //Mouse出现的方法. void MouseShow() { timer += Time.deltaTime; //每过1s生产一个地鼠. if(timer > 1) { timer -= 1; ranIndexX = Random.Range(0, 3); ranIndexY = Random.Range(0, 3); //通过对象池生成地鼠. MousePool.Instance.InstantiateMouse(mousePrefab, new Vector3(ranIndexX * 2, 0, ranIndexY * 2), Quaternion.identity); } } //锤子的移动和动画控制器. void HammerMove() { if(Input.GetMouseButtonDown(0)) { anim.SetTrigger("Attack"); } //将锤子的坐标转换为其在屏幕上的坐标,并保持y轴位置不变. screenPos = Camera.main.WorldToScreenPoint(new Vector3(transform.position.x, 1, transform.position.z)); //鼠标位置. newPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPos.z); //将得到的屏幕坐标转换为世界坐标. transform.position = Camera.main.ScreenToWorldPoint(newPosition); } }
最后是对象池的代码:
public class MousePool { //对象池. Dictionary<string, List<GameObject>> pool = new Dictionary<string, List<GameObject>>(); //单例模式. private static MousePool instance; public static MousePool Instance { get { if(instance == null) { instance = new MousePool(); } return instance; } } private MousePool(){} //对象的存储类别. string tags; GameObject mouse; //对象池管理方法. public GameObject InstantiateMouse(GameObject prefab, Vector3 position, Quaternion rotation) { tags = prefab.tag; //如果对象池中存在该类别并且数码大于0,则从对象池中取出该对象,否则实例化一个该对象. if(pool.ContainsKey(tags) && pool[tags].Count > 0) { mouse = pool[tags][0]; pool[tags].Remove(mouse); mouse.transform.position = position; mouse.transform.rotation = rotation; mouse.SetActive(true); }else{ if(!pool.ContainsKey(tags)) { pool.Add(tags, new List<GameObject>()); } mouse = GameObject.Instantiate(prefab, position, rotation) as GameObject; } return mouse; } //回收方法. public void RecycleMouse(GameObject mouse) { pool[mouse.tag].Add(mouse); mouse.SetActive(false); } }
好了,游戏基本完成
网页版预览
PC版下载
相关文章推荐
- NYOJ 358 取石子(五)(斐波那契博弈)
- objective_c
- 数据结构Java 线性表与顺序表
- JNI中的string返回jstring
- 电脑史话(1)
- UI设计师产品构思过程中需要有一个系统思维方向
- ef之 entitystate状态
- 图像处理函数详解——imfilter
- 电脑史话(2)
- 51nod 1004 n^n的末位数字
- 区分Activity的四种加载模式 (写的真心棒)
- 四种会话跟踪技术
- 电脑史话(3)
- CodeForces 510E Fox And Dinner
- 《剑指Offer》面试题:按字典序打印出该字符串中字符的所有排列
- Android Studio下的library转换成Eclipse下可使用的library
- 编程是一个及其痛苦的事
- 组织Go的源码
- 使用 SQLiteDatabase 操作 SQLite 数据库
- 关于PADS的一些概念和实用技巧(一)