2019-05-06 17:10:08 qq_38229886 阅读数 510
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4639 人正在学习 去看看 张刚

 

写在前面

3D拾取功能在实际项目开发中是一种非常常用的功能,尤其是在3D游戏中,拾取技术是必不可少的基础操作,拾取技术极大的增强了游戏的交互性。

3D拾取原理

简单的来说,3D拾取是通过屏幕上的一个点与摄像机的位置(摄像机控件原点)构成一条射线,然后与场景中物体进行相交,判断是否相交,进而进行拾取操作,这个相交判断的实际是射线与三角形的相交判断算法。在实际开发中,更多的使用包围盒等算法。想要深入了解3D拾取原理的同学,请点击。深入了解3D拾取原理

Unity中简单实现3D拾取功能

1: 代码编写

  (1) 发射一条射线: Ray ray = Camera.main.ScreenPointToRay(Touch.position);

  (2) 检测撞到那个物体: Raycast hit; bool Physics.Raycast(ray, out hit);

  (3) hit.transform, 获得物体的transform组件, name可以获得被碰撞的物体的名字;

  (4) Camera.main获取当前我们的主Camera

  (5) 如果要拾取,需要有一个碰撞器

2.源代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CatchScript : MonoBehaviour
{
    private GameObject gameobj;
    private bool CubeFlag = false;
    private bool SphereFlag = false;
    private bool CapsuleFlag = false;
    public Texture2D texture;
    void Start()
    {

    }
    void Update()
    {
        //鼠标监听 是否点击
        if (Input.GetMouseButtonDown(0))
        {
            //创建射线 Camera.main 只是代表tag标签为main camera 的摄像机 其可以替换为任何摄像机
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            //创建碰撞体对象
            RaycastHit hit;
            //判断是否碰撞
            if (Physics.Raycast(ray,out hit))
            {
                //打印拾取物体的名称
                Debug.Log(hit.transform.name);
                SetObj(hit.transform.name);        
            }
            else
            {
                CubeFlag = false;
                CapsuleFlag = false;
                SphereFlag = false;
            }
        }

        if (CubeFlag)
        {
            gameobj.GetComponent<Renderer>().material.mainTexture = texture;
            gameobj.transform.Rotate(0, 10, 0);
        }

        if (SphereFlag)
        {
            gameobj.transform.Translate(0, 0.02f, 0);
        }
        if (CapsuleFlag)
        {
            gameobj.transform.Rotate(0, 10, 0);
        }

    }
    void SetObj(string hitname)
    {
        switch(hitname)
        {
            case "Cube":

                gameobj = GameObject.Find("Cube");
                CubeFlag = true;
                CapsuleFlag = false;
                SphereFlag = false;
                break;
            case "Sphere":
                gameobj = GameObject.Find("Sphere");
                SphereFlag = true;
                CubeFlag = false;
                CapsuleFlag = false;
                break;
            case "Capsule":
                gameobj = GameObject.Find("Capsule");
                CapsuleFlag = true;
                CubeFlag = false;
                SphereFlag = false;
                break;
            default:
                CubeFlag = false;
                CapsuleFlag = false;
                SphereFlag = false;
                break;
        }
    }
}

3.将该脚本挂在对应摄像机上。

这样我们就在Unity中简单实现了3D拾取功能。

2013-07-20 14:59:28 a2587539515 阅读数 3193
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4639 人正在学习 去看看 张刚

账号被盗,文章被修改,博主已将博文删除

2014-04-20 12:08:40 cooelf 阅读数 3923
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4639 人正在学习 去看看 张刚

工程包下载:Unity3D虚拟现实开发之角色拾取

//这个是成品图

角色拾取的原理是:由摄像机与屏幕上鼠标点击的位置确定一条射线,由此射线射向3D世界,最先和此射线相交的物体就是被选中的物体,然后对该物体的操控编写对应的代码即可。具体代码如下:

#鼠标控制
#pragma strict

var flag : boolean=true ;//通过初始化flag赋给物体初始坐标
function Start(){
}
function Update () {
	 if (Input.GetMouseButton (0)) {    

		//声明一条由鼠标位置发出垂直于屏幕的射线
     	var ray = Camera.main.ScreenPointToRay (Input.mousePosition);    
         	var hit : RaycastHit;		
		if (Physics.Raycast (ray, hit)){		//判断此物理事件
            if(hit.transform.root.transform==this.transform) {	
            	flag=!flag;	
    } } } 
    if(flag){
		this.transform.position=Vector3(0,0,2);
	}
	else if(!flag){
		this.transform.position=Vector3(2,0,2);
	}
}

下面是相关的说明:

1.关于Physics.Raycast:

根据Unity圣典的解释:

Returns

bool - True when the ray intersects any collider, otherwise false.

当光线投射与任何碰撞器交叉时为真,否则为假。

Description描述

Casts a ray against all colliders in the scene.

在场景中投下可与所有碰撞器碰撞的一条光线。

因此,这里要求角色必须是或者添加了碰撞器,否则

if (Physics.Raycast (ray, hit)){        //判断此物理事件
            if(hit.transform.root.transform==this.transform) {    
                flag=!flag;    


这个语句不会按照预期执行,flag不会发生改变。

2.调整主摄影机的属性,使视野显示需要操作的角色。



2018-01-30 16:42:53 zhandar44 阅读数 2484
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4639 人正在学习 去看看 张刚

此例子为2D场景

 

原理:通过操控角色碰撞可拾取物体,通过按键确认拾取到角色指定位置。

具体代码实现

角色代码

public class playctr: MonoBehaviour
{
    public Transform pphead;          //物体头部位置
    private GameObject heads;         //获取头部物体
    bool gethead = false;             //判断头部物体显示
    void OnTriggerStay2D(Collider2D other)
    {
        if (other.gameObject.tag == "head")          //碰撞的物体标签为头部时
        {
            Debug.Log("please get E");
            if (Input.GetKey(KeyCode.E))             //按下e装备物体
            {
                other.gameObject.SetActive(false);  //取消被拾取物体的显示
                other.gameObject.tag = "phead";     //改变被拾取物的标签
                gethead = true;                     //存在可装备头部物体
                heads = other.gameObject;           //获取头部物体
            }
        }
    }
    void FixedUpdate()
    {
        if (gethead)//当存在可装备头部物体
        {
            heads.gameObject.SetActive(true); //显示物体
            heads.GetComponent<Transform>().position = pphead.GetComponent<Transform>().position;//将物体绑定在人物身上
        }
        if (Input.GetKey(KeyCode.G) && heads.gameObject.tag == "phead")//当按下G且头部物体标签为phead时(简单说就是脱下装备)
        {
            gethead = false;//改变头部物体判断为不存在
        }
    }
}

被拾取物体代码

 

public class movv : MonoBehaviour
{
    bool tlow = false;         //装备存在物理属性掉落
    public float stoptime;     //改变装备为触发器等待时间
   
    void FixedUpdate()
    {
        if (Input.GetKey(KeyCode.G) && this.gameObject.tag == "phead")//按下g脱掉装备
        {
            this.gameObject.tag = "head";
            tlow = true; 
        }
if (tlow) //装备变为存在物理属性
        {
            this.GetComponent<BoxCollider2D>().isTrigger = false;
            this.GetComponent<Rigidbody2D>().gravityScale = 1;
        }
        if (this.GetComponent<Rigidbody2D>().gravityScale == 0) //装备的重力为0(改变为触发器)
        {
            this.GetComponent<BoxCollider2D>().isTrigger = true;
        }
        
    }
    void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.collider.tag == "land")//碰撞地面 
        {
            StartCoroutine(stop());

        }
    }
    IEnumerator stop()//等待时间过后改变装备属性
    {
        yield return new WaitForSeconds(stoptime);
        tlow = false;
        this.GetComponent<Rigidbody2D>().gravityScale = 0;
    }

}

拾取过程:

1、开始时

物体属性

2、拾取物体至头部

     

3、脱下物体时

          

 

4、脱下后

 

角色设置:

   

相关解释:

1、拾取物体需要提前在角色设定好拾取后出现的位置。

 

2、需要设定被拾取物体改变为触发器的时间。假设没有设置时间,当被拾取物体碰撞地面立刻变为触发器,会保持原来的速度一直下落,所以设定这个时间相当于冷却,当被拾取物体碰撞地面,等待一段时间再改变属性为触发器。

 

 

此方法为初学unity所想,如有错误请谅解,还望指正。

2019-11-19 22:41:31 DY_1024 阅读数 6
  • Unity3D入门到精通-(3)Unity资源管理精讲

    本次系列课程的目标是让Unity3D初学者掌握Unity3d的资源管理技术进行了全面介绍,特别对AssetBundle资源如何进行更新,以及加载(依赖资源加载)进行了系统的介绍。 适合对象:Unity初学开发者,Unity中级开发者,网络程序开发者,所有对游戏开发有兴趣的人员。 学习条件:有一定的Unity3D基础,了解C#的基本开发知识。

    4639 人正在学习 去看看 张刚

3D拾取的原理请看本人博客的:DX9中的3D拾取,此文章只记录Unity中的3D拾取 。

1、创建一个Cube,当我们使用鼠标点击二维屏幕的时候,相当于从发出一条射线,然后将这条射线和三维世界中的物体进行判断相交,第一个相交的物体就是点击到的物体。

2、给Cube添加脚本:

using System.Collections;  
using System.Collections.Generic;  
using UnityEngine;  
  
public class RayTest : MonoBehaviour  
{  
    // Start is called before the first frame update  
    void Start()  
    {  
          
    }  
  
    // Update is called once per frame  
    void Update()  
    {  
        if(Input.GetMouseButtonDown(0))  
        {  
            // 获取从鼠标点击发射的射线  
            // Camera.main能够获取当前场景中的主摄影机  
            // ScreenPointToRay函数能够将屏幕点击的点转换成一条射线,参数就是屏幕点击的坐标  
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);  
            // 撞击到了哪一个3D物体  
            RaycastHit hit;  
  
            if (Physics.Raycast(ray, out hit))  
            {  
                // 经过判断之后,hit里面存放的就是和射线第一个相交的物体的信息  
   // 点击cube之后,打印cube的信息
                Debug.Log(hit.transform.name);   
            }  
  
        }  
    }  
}  

 

unity3d 参考坐标系

阅读数 722

3D拾取技术

阅读数 1110

没有更多推荐了,返回首页