9. unity物体获取、资源使用、定时和向量运算

1. 脚本中获取物体对象

第一种方式:使用Find函数(不推荐)
这种方法不太方便,且编辑器中可能会对模型的名称进行更改,容易出错。

    void Start()
    {
        GameObject node = GameObject.Find("正方体");//查找获取编辑器中名称为“正方体”的模型
    }

第二种方式:使用属性赋值的方式(推荐使用)
这种方法和组件的引用时类似的,在脚本文件中设置一个属性,然后在编辑器中对这个属性进行赋值,这样的好处是不管模型名称或位置怎么改动,编辑器会自动适应这种变化,不易出错。

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

public class BallScript : MonoBehaviour
{
    public GameObject node; //在此处设置一个属性

    // Start is called before the first frame update
    void Start()
    {
        //赋值后就可以对物体传输过来的物体进行一些想要的操作
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

然后再在编辑器中对脚本中设置的属性进行赋值即可
9. unity物体获取、资源使用、定时和向量运算_第1张图片

2. 父级/子级物体的获取

在unity中,父级子级是由Transform这个类来维护的
获取父级:

Transform parent = this.transfrom.parent;

获取父级节点:

GameObject parentNode = this.transform.parent.gameobject;

获取子级:

//第一种:遍历查找
foreach(Transform child in transform)
{
    Debug.Log("* 子物体:" + child.name);
}
//第二种:索引查找
Transform child2 = this.transform.GetChild(0);
Debug.Log("* 子物体:" + child2.name);
//第三种:名称查找
Transform child3 = this.transform.Find("正方体");
Debug.Log("* 子物体:" + child3.name);

3. 物体的操作

3.1 设置父级节点

this.transform.SetParent(node);//node为某一个节点模型
this.transform .SetParent(null);//null表示设置为一级节点

3.2 隐藏 / 显示物体

Transform child = this.transform.Find("/aa");//前面的 / 表示在根节点开始查找
if (child.gameObject.activeSelf)//如果当前物体显示(activeself用于判断当前物体是否是激活状态)
 {
     child.gameObject.SetActive(false);//隐藏物体
 }
 else
 {
     child.gameObject.SetActive(true);//显示物体
 }

4. 资源的使用

在脚本中,也可以引用一个资源
比如:
AudioClip 音频文件
Texture 纹理贴图
Material 材质

举例:脚本控制音频文件 audioclip
首先在界面编辑器当中给某一个物体挂载一个AudioSource组件,此时不用在界面中设定其AudioClip属性,这个在其挂载的脚本中进行设置,如图:(一般情况下,在界面编辑器中添加一个组件后,可以直接将资源文件拖放到对应属性内,不过现在要在脚本中进行设置)
9. unity物体获取、资源使用、定时和向量运算_第2张图片
然后在这个小球模型上挂载一个脚本,代码如下:

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

public class BallScript : MonoBehaviour
{
    public AudioClip audioclipSucess; //定义一个属性,用于接收界面编辑器设置的'成功提示音'

    public AudioClip audioclipFail;//定义一个属性,用于接收界面编辑器设置的'失败提示音'

    private AudioSource audio;

    // Start is called before the first frame update
    void Start()
    {
        audio = this.GetComponent<AudioSource>();//获取当前模型下的audiosource组件
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.A))
        {
            audio.PlayOneShot(audioclipSucess);//播放一次
        }
        if(Input.GetKeyDown(KeyCode.D))
        {
            audio.PlayOneShot(audioclipFail);//播放一次
        }
    }
}

挂载代码后,还需在界面编辑器中将上面的两个属性进行指定,如下图所示,指定后运行程序即可。
9. unity物体获取、资源使用、定时和向量运算_第3张图片

5. 资源数组

在定义属性时,如果需要一个变量存储多个内容,可以考虑使用数组来实现,在脚本中设置一个数组变量:

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

public class KaTongLogic : MonoBehaviour
{

    public AudioClip[] audioClips;//添加一个数组类型的变量

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
        	NextAudio();
        }
    }
	private void NextAudio()
	{
		//随机播放
		int index = Random.Range(0,audioClips.Length);
		AudioClip audio = this.audioClips[index];
		AudioSource audioSource = this.GetComponent<AudioSource>();
		audioSource.clip = audio;	//给组件属性赋值
		audioSource.Play();	//开始播放
	}
}

在界面中对数组属性进行赋值时,可以多次赋值:
9. unity物体获取、资源使用、定时和向量运算_第4张图片

6. 定时调用

定时调用Invoke,即常说的定时器,继承自MonoBehavior,常用函数如下:
Invoke(func,delay):只调用一次
InvokeRepeating(func,delay,interval):第一次调用延迟delay时间,后面每次循环调用的间隔时间按照interval执行
IsInvoking(func):判断是否正在调度中
CancelInvoke(func):取消调用、从调度队列中移除

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

public class KaTongLogic : MonoBehaviour
{

    public AudioClip[] audioClips;

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("* Start。。。。" + Time.time);

        //注意函数名要以字符串的形式给出
        this.Invoke("DoSomething",1);// 1 秒后调用这个函数

        this.InvokeRepeating("DoSomething",2,4);第一次是2秒后调用这个函数,后面就是按照间隔4秒循环调用
    }

    // Update is called once per frame
    void Update()
    {

    }

    public void DoSometing()
    {
        Debug.Log("* DoSomethis。。。。" + Time.time);
    }
}

7. unity线程问题??

在unity中是没有多线程的,不用考虑并发、多线程啥的。。。
可以使用线程ID进行验证
using System.Threading;
Thread.CurrentThread.ManagedThreadId;
分别在start()函数、update()函数和定时函数中打印出线程ID,发现ID号是一样的

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

using System.Threading;

public class KaTongLogic : MonoBehaviour
{

    public AudioClip[] audioClips;

    // Start is called before the first frame update
    void Start()
    {
        Debug.Log("* Start。。。。" + Time.time);

        Debug.Log("* Start...." + Thread.CurrentThread.ManagedThreadId);//输出当前函数所在线程ID

        //注意函数名要以字符串的形式给出
        this.Invoke("DoSomething",1);// 1 秒后调用这个函数

        this.InvokeRepeating("DoSomething",2,4);//第一次是2秒后调用这个函数,后面就是按照间隔4秒循环调用
    }

    // Update is called once per frame
    void Update()
    {
        Debug.Log("* Update...." + Thread.CurrentThread.ManagedThreadId);//输出当前函数所在线程ID
    }
	
	//延迟调用函数
    public void DoSometing()
    {
        Debug.Log("* DoSometing...." + Thread.CurrentThread.ManagedThreadId);//输出当前函数所在线程ID
        Debug.Log("* DoSomethis。。。。" + Time.time);
    }
}

8. 案例:利用定时器实现速度的渐变

实现模型的缓慢加速旋转和缓慢停止旋转
代码:

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


public class KaTongLogic : MonoBehaviour
{
    public float maxSpeed = 1000;

    float m_speed = 0;//当前速度
    bool m_speedUp = false;//是否加速
    // Start is called before the first frame update
    void Start()
    {
        this.InvokeRepeating("AdjustSpeed", 0.1f,0.1f);//循环调用
    }

    // Update is called once per frame
    void Update()
    {
        //点一下加速,再点减速,交替执行
        if(Input.GetMouseButtonDown(0))
        {
            m_speedUp = !m_speedUp;
        }
        if (m_speed > 0)
        {
            this.transform.Rotate(0, 0, m_speed * Time.deltaTime, Space.Self);
        }

    }

    public void AdjustSpeed()
    {
        if (m_speedUp)
        {
            //阈值判断
            if(m_speed < maxSpeed)
            {
                m_speed += 20;
            }
        }
        else
        {
            m_speed -= 20;
            //阈值判断
            if(m_speed < 0)
            {
                m_speed = 0;
            }
        }
    }
}

实际效果:

unity定时器实现速度渐变

10. unity中的向量

向量:有方向有长度,在unity当中使用较多的是Vector3三维向量。

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

public class KaTongLogic : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //两个API
        Vector3 v1 = new Vector3 (6, 8, 0);

        float len = v1.magnitude; //求向量的长度
        Debug.Log("v1的长度:" + len);

        Vector3 v2 = v1.normalized;//向量的标准化
        Debug.Log("v1的标准化:" + v2);

        //几个常量
        Vector3 vZero = Vector3.zero;//即(0,0,0)
        Vector3 vUp = Vector3.up;//即(0,1,0)
        Vector3 vRight = Vector3.right;//即(1,0,0)
        Vector3 vForward = Vector3.forward;//即(0,0,1)

        Vector3 a = new Vector3(3, 4, 0);
        Vector3 b = new Vector3(5, 6, 0);

        //向量加法
        Vector3 c = a + b;

        //向量减法
        Vector3 d = a - b;

        //向量乘法
        Vector3 e = a * 2;//标量乘法
        float f = Vector3.Dot(a,b);//点积
        Vector3 g = Vector3.Cross(a, b);//差积

        //向量赋值
        Vector3 h = a;//注意不能赋值为null
    }

    // Update is called once per frame
    void Update()
    {

    }
}

10.1 向量测距

可用于计算两个物体之间的距离,确切的说是计算两个物体轴心点之间的距离,测距之前应先检查一下两个物体之间的轴心点是否在一个平面上,不然可能存在误差

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

public class KaTongLogic : MonoBehaviour
{
    public GameObject target;
    // Start is called before the first frame update
    void Start()
    {
        Vector3 p1 = this.transform.position;//当前物体的坐标(相对于原点)
        Vector3 p2 = target.transform.position;//目标物体的坐标(相对于原点)
        
        Vector3 direction = p2 - p1;//计算两者间的方向向量
        float distance = direction.magnitude;//计算距离

        //使用API进行计算
        float distance2 = Vector3.Distance(p2, p1);

        Debug.Log("* 两者之间的距离:" + distance );
        Debug.Log("* 两者之间的距离:" + distance2);
    }

    // Update is called once per frame
    void Update()
    {

    }
}

辅助记忆:
9. unity物体获取、资源使用、定时和向量运算_第5张图片

10.2 向量的应用

比如在脚本中设定物体的移动速度,可以单独设置一个float类型的值,然后使用translate()函数指定物体在哪个方向移动,但这样并不通用,无法做到任意的更改移动方向,可以使用向量的方式来指定。
示例:

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


public class KaTongLogic : MonoBehaviour
{
    public Vector3 speed; //定义一个三维向量来控制物体移动(包括方向和速度)

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        Vector3 delta = speed * Time.deltaTime;

        this.transform.Translate(delta, Space.Self);
    }
}

这样就可以在界面编辑器中任意指定物体移动的方向和速度了,在下图中的x,y,z输入框内输入数值,可任意指定:
9. unity物体获取、资源使用、定时和向量运算_第6张图片

持续更新中,请大家多多关注…

你可能感兴趣的:(Unity,unity)