屏幕坐标和世界坐标的转换+对象池技术(3D打地鼠小游戏)

游戏中可能经常会遇到需要某个物体跟着鼠标移动,然后又需要把物体放在某个鼠标指定的位置

实现方式

Camera.main.WorldToScreenPoint

Camera.main.ScreenToWorldPoint

3D打地鼠实例

我这里用到的素材都比较简陋,几乎全是用Unity做的

首先是锤子

屏幕坐标和世界坐标的转换+对象池技术(3D打地鼠小游戏)

就是两个Cylinder,在把手的位置放一个空物体用于模拟锤子的动作,命名为Hammer,把锤子作为Hammer的子物体,给Hammer添加Animation动画:

屏幕坐标和世界坐标的转换+对象池技术(3D打地鼠小游戏)

在三个关键帧位置设置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();
}
} }

屏幕坐标和世界坐标的转换+对象池技术(3D打地鼠小游戏)

在四个关键帧位置设置Capsule的Position分别为(0, -1, 0),(0, 0, 0),(0, 0, 0),(0, -1, 0)

将Mouse拖为预设体

锤子的动画状态机:

屏幕坐标和世界坐标的转换+对象池技术(3D打地鼠小游戏)

布置洞口

为了能看到地鼠的出没,我这里用PS简单的做了一张有有透明洞口的png图片:

屏幕坐标和世界坐标的转换+对象池技术(3D打地鼠小游戏)<=这里有一张看不见的图片。。。

新建一个Material,将Shader该为Transparent/Diffuse,把上面那张图片拖上去

新建9个Cube,把刚才新建的Material赋予它,改变位置和大小,调整摄像机,最终结果如下:

屏幕坐标和世界坐标的转换+对象池技术(3D打地鼠小游戏)

下面是锤子上的代码:

 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 = ; //地鼠的预设体.
public GameObject mousePrefab;
int ranIndexX;
int ranIndexY; //Mouse出现的方法.
void MouseShow()
{
timer += Time.deltaTime;
//每过1s生产一个地鼠.
if(timer > )
{
timer -= ;
ranIndexX = Random.Range(, );
ranIndexY = Random.Range(, );
//通过对象池生成地鼠.
MousePool.Instance.InstantiateMouse(mousePrefab, new Vector3(ranIndexX * , , ranIndexY * ), Quaternion.identity);
}
} //锤子的移动和动画控制器.
void HammerMove()
{
if(Input.GetMouseButtonDown())
{
anim.SetTrigger("Attack");
} //将锤子的坐标转换为其在屏幕上的坐标,并保持y轴位置不变.
screenPos = Camera.main.WorldToScreenPoint(new Vector3(transform.position.x, , 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 > )
{
mouse = pool[tags][];
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版下载

上一篇:[Android Studio 1A] – 插件


下一篇:解决前端跳转路由公共导航栏样式消失问题