zoukankan      html  css  js  c++  java
  • 屏幕坐标和世界坐标的转换+对象池技术(3D打地鼠小游戏)

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

    实现方式

    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添加脚本

     1 public class MouseController : MonoBehaviour {
     2 
     3     /// <summary>
     4     /// Recycles the mouse.
     5     /// </summary>
     6     public void RecycleMouse()
     7     {
     8 //        Destroy(transform.parent.gameObject);
     9 
    10         //对象池回收.
    11         MousePool.Instance.RecycleMouse(transform.parent.gameObject);
    12     }
    13 
    14     //被打到时的触发方法.
    15     void OnTriggerEnter(Collider other)
    16     {
    17         if(other.tag == "Hammer")
    18         {
    19             print("Score");
    20             RecycleMouse();
    21         }
    22     }
    23     
    24 }

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

    将Mouse拖为预设体

    锤子的动画状态机:

    布置洞口

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

    <=这里有一张看不见的图片。。。

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

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

    下面是锤子上的代码:

     1 public class HammerController : MonoBehaviour {
     2     
     3     Animator anim;
     4     Transform head;
     5 
     6     void Start () {
     7         anim = this.GetComponent<Animator>();
     8         head = GameObject.Find("Head").transform;
     9     }
    10     
    11     Vector3 newPosition;
    12     Vector3 screenPos;
    13 
    14     void Update () {
    15         MouseShow();
    16         HammerMove();
    17     }
    18 
    19     //记时器.
    20     float timer = 0;
    21 
    22     //地鼠的预设体.
    23     public GameObject mousePrefab;
    24     int ranIndexX;
    25     int ranIndexY;
    26 
    27     //Mouse出现的方法.
    28     void MouseShow()
    29     {
    30         timer += Time.deltaTime;
    31         //每过1s生产一个地鼠.
    32         if(timer > 1)
    33         {
    34             timer -= 1;
    35             ranIndexX = Random.Range(0, 3);
    36             ranIndexY = Random.Range(0, 3);
    37             //通过对象池生成地鼠.
    38             MousePool.Instance.InstantiateMouse(mousePrefab, new Vector3(ranIndexX * 2, 0, ranIndexY * 2), Quaternion.identity);
    39         }
    40     }
    41 
    42     //锤子的移动和动画控制器.
    43     void HammerMove()
    44     {
    45         if(Input.GetMouseButtonDown(0))
    46         {
    47             anim.SetTrigger("Attack");
    48         }
    49 
    50         //将锤子的坐标转换为其在屏幕上的坐标,并保持y轴位置不变.
    51         screenPos = Camera.main.WorldToScreenPoint(new Vector3(transform.position.x, 1, transform.position.z));
    52 
    53         //鼠标位置.
    54         newPosition = new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenPos.z);
    55 
    56         //将得到的屏幕坐标转换为世界坐标.
    57         transform.position = Camera.main.ScreenToWorldPoint(newPosition);
    58     }
    59 
    60 }

    最后是对象池的代码:

     1 public class MousePool  {
     2 
     3     //对象池.
     4     Dictionary<string, List<GameObject>> pool = new Dictionary<string, List<GameObject>>();
     5 
     6     //单例模式.
     7     private static MousePool instance;
     8     public static MousePool Instance {
     9         get {
    10             if(instance == null)
    11             {
    12                 instance = new MousePool();
    13             }
    14             return instance;
    15         }
    16     }
    17     private MousePool(){}
    18 
    19     //对象的存储类别.
    20     string tags;
    21     GameObject mouse;
    22 
    23     //对象池管理方法.
    24     public GameObject InstantiateMouse(GameObject prefab, Vector3 position, Quaternion rotation)
    25     {
    26         tags = prefab.tag;
    27 
    28         //如果对象池中存在该类别并且数码大于0,则从对象池中取出该对象,否则实例化一个该对象.
    29         if(pool.ContainsKey(tags) && pool[tags].Count > 0)
    30         {
    31             mouse = pool[tags][0];
    32             pool[tags].Remove(mouse);
    33             mouse.transform.position = position;
    34             mouse.transform.rotation = rotation;
    35             mouse.SetActive(true);
    36         }else{
    37             if(!pool.ContainsKey(tags))
    38             {
    39                 pool.Add(tags, new List<GameObject>());
    40             }
    41             mouse = GameObject.Instantiate(prefab, position, rotation) as GameObject;
    42         }        
    43         return mouse;
    44     }
    45 
    46     //回收方法.
    47     public void RecycleMouse(GameObject mouse)
    48     {
    49         pool[mouse.tag].Add(mouse);
    50         mouse.SetActive(false);
    51     }
    52 
    53 }

    好了,游戏基本完成

    网页版预览

    PC版下载

  • 相关阅读:
    深入理解 RPC
    Redis 深度历险
    tomcat性能优化
    高性能IO之Reactor模式
    常用sql语句整理[SQL Server]
    SQLite遇到的关于x64、x86问题
    C#和Javascript的try…catch…finally的一点差别
    C#写Windows服务
    Windows_7_休眠按钮没有了_如何找回?
    XmlReader读取XML
  • 原文地址:https://www.cnblogs.com/zhenlong/p/4862390.html
Copyright © 2011-2022 走看看