Unity面试题整理(3)--unity知识点扫盲

来源:互联网 发布:wp 添加js 编辑:程序博客网 时间:2024/06/05 16:52
MeshRenderer中material 和 sharedMaterial的区别
获取
Material material = A.GetComponent<MeshRenderer> ().material; (1)
Material sharedMaterial = A.GetComponent<MeshRenderer>().sharedMaterial; (2)
如果两个对象AB引用了同一个材质M,那么通过(1)获取的material是M的一个实例化的对象,对其进行任何操作不会对实际的材质M产生任何影响,也不会对对象B产生任何影响。如果通过(2)获取sharedMaterial,返回的就是材质M本身,对其进行任何操作都会改变M的属性,也会影响到对象B。
material便于测试,但会产生额外内存,效率没有sharedMaterial好,所以可以将开发过程和发布区分开来
  1. public static Material GetMaterial(Renderer render)  
  2. {  
  3.     #if UNITY_EDITOR  
  4.         return render.material;  
  5.     #else  
  6.         return render.sharedMaterial;  
  7.     #endif  

MonoBehaviour生命周期
官方给出的流程图:https://docs.unity3d.com/Manual/ExecutionOrder.html

物体跟随鼠标移动和缩放
    bool isMouseIn=false;
    bool isDragged=false;
    Vector3 initOffset = Vector3.zero;
    void OnMouseDown()
    {  
        if(isMouseIn)
        {
            isDragged = true;
            Vector3 objScreenPos = Camera.main.WorldToScreenPoint (go.transform.position);
            Vector3 mousePos = Input.mousePosition;
                         //这里要注意的是,要计算鼠标的3d位置,需要正确的z坐标才能得到
                         //直接用Camera.main.ScreenToWorldPoint(mousePos)会得到错误的结果
            //这里使用物体的z坐标
            mousePos = Camera.main.ScreenToWorldPoint (new Vector3(mousePos.x,mousePos.y,objScreenPos.z));
            initOffset = transform.position - mousePos; //鼠标按下时,记录最初鼠标位置与物体位置的offset
        }
    }
     void OnMouseUp(){  
        isDragged = false;
    }
    void OnMouseEnter(){  
        isMouseIn = true;
    }
    void OnMouseExit(){  
        isMouseIn = false;
    }
    void OnMouseDrag()
    {
        if(isDragged)
        {
            Vector3 objScreenPos = Camera.main.WorldToScreenPoint (go.transform.position);
            Vector3 mousePos = Input.mousePosition;
            mousePos = Camera.main.ScreenToWorldPoint (new Vector3(mousePos.x,mousePos.y,objScreenPos.z));
            go.transform.position = mousePos + initOffset;//物体位置=鼠标位置+初始offset
        }
    }
          //物体随滚轮进行缩放
    float scale=1;
    void Update () {
        scale += Input.GetAxis ("Mouse ScrollWheel");
        scale = Mathf.Clamp (scale, 0.5f, 5f);
        if (scale> 0.5f && scale<5)
        {
            go.transform.localScale = new Vector3 (scale,scale,scale);
        }
    }

DontDestroyOnLoad重复加在对象
为了在切换场景的时候,保留一些全局的对象,需要将这些为对象设置DontDestroyOnLoad(obj),但是如果在返回这个场景的时候,DontDestroyOnLoad(obj)又会调用一遍,会导致对象重复。
解决思路:from:http://www.xuanyusong.com/archives/2938
1.创建一个单独的场景来初始化这些全局对象,并且这个场景只进入一次
2.使用static constructor

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
using UnityEngine;
using System.Collections;
 
public class Global :MonoBehaviour
{
public static Global instance;
 
static Global()
{
GameObject go = new GameObject("Globa");
DontDestroyOnLoad(go);
instance = go.AddComponent<Global>();
}
 
public void DoSomeThings()
{
Debug.Log("DoSomeThings");
}
 
void Start ()
{
Debug.Log("Start");
}
 
}

物理碰撞和触发器
碰撞
static collider:只有collider,没有rigid body,特点可以与其它刚体发生碰撞,但是不能动,所以物理引擎不模拟其碰撞效果
rigidbodycollider:有collider和rigidbody,特点是可以碰撞,碰撞后,物理引擎会模拟其碰撞效果,如被撞飞,旋转等
kinematic rigidbody collider:有collider和rigidbody,可以发生碰撞,但是物理引擎不模拟其碰撞效果
MonoBehaviour中,获取碰撞动回调函数,注意参数是Collision
void OnCollisionEnter(Collision e)  
void OnCollisionStay(Collision e) 
void OnCollisionExit(Collision e)  
碰撞矩阵

矩阵的记法很简单:static 和 kinematic的collider只和rigidbody collider发生碰撞,而rigidbody collider和这三种都可以碰撞

触发器
在collider中有一个选项叫做IsTrigger,如果勾选上它,那么这个物体的collider就变成了触发器。触发器的特点是只获取碰撞信息,物理引擎不再模拟碰撞效果。
MonoBehaviour中,获取触发器回调函数,注意参数是Collider
void OnTriggerEnter(Collider e) 
void OnTriggerStay(Collider e) 
void OnTriggerExit(Collider e) 
触发器矩阵

这个矩阵看着很复杂,其实也很好记:static trigger collider和static trigger collider与static collider都不触发,(很好理解,因为静态的collider是不能动嘛),而rigidbody trigger collider 、 kinematic rigidbody trigger collider 与任意collider 、 trigger collider都会触发。




0 0