您的位置:首页 > 其它

屏幕坐标和世界坐标的转换+对象池技术(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添加脚本

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版下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: