Unity3D / 计算机技术 · 2020年3月11日 13

Unity API常用方法记录

前言:

跟着siki学院的这个课——Unity API常用方法和类详细讲解

来学习Unity脚本,我把一些自己比较陌生的做了记录

 

 

 

 

 


帮助文档

我们可以在Unity上边菜单栏的Help找到Unity Manual ,点击打开,这就跳转到了一个网页,这个就是Unity官方的用户手册网页

同一网站上的Scripting API,就是API文档

在我们学习Unity的过程中,这两个文档会有很大的帮助。

 

 


常见类的方法或属性记录(一)

 

事件方法

我们可以在https://docs.unity3d.com/Manual/ExecutionOrder.html这个网页找到Unity中的事件方法

它的那张长图非常棒,有很多解释(虽然是英文)。

比如 Reset这个方法,它是只在编辑器模式下会被调用(即发布之后不会调用),我们在编辑器模式下,点击一个组件右边齿轮的reset,其实就是调用了这个reset方法,它把组件的属性还原了。

 

Time类

https://docs.unity3d.com/ScriptReference/Time.html

Time类,有很多静态变量

其中比较重要的就是deltatime,即每一帧运行的时间

realtimeSinceStartup 从游戏开始到现在的总时间

time 从程序开始执行到现在的时间

smoothDeltaTime 更加平滑均匀的deltatime

fixedTime  表示FixedUpdate已经执行的时间

FixedUpdate:

固定更新方法,和物理相关的操作代码,都要写在此方法中。

固定更新的时间是0.02s,1秒执行50次,可在Edit—>Project Settings—>Time面板中的Fixed Timestep查看。

timeScale 可以控制时间(为n,则时间是n倍)

设置 Time.timeScale 为 0 将会暂停所有和帧率无关的事情。这些主要是指所有的物理事件和依赖时间的函数、刚体力和速度等,而且 FixedUpdate 会被暂停(不是Update),因为FixedUpdate函数是根据时间来进行更新的。

但是,Update 函数本身的执行是不会受 Time.timeScale 的影响的。Update 是依赖你的机器的,它的调用次数和你的机器渲染一样快慢(一些特殊情况除外);性能高的机器,帧率高,Update 函数执行次数也就多。因此,当使用 Time.timeScale = 0 时,游戏看起来是被冻结了,这是因为所有和时间有关的事情都被暂停了。但是,我们的游戏仍在渲染,也就是说 Update 函数仍在执行。无论 Time.timeScale 等于多少,Update 和 LateUpdate 都会去执行。所有的动画都是基于时间来的,因为Time.timeScale = 0了,所以 Time.time 也就不会在变化了。当 Time.timeScale 为 0 时,Time.deltaTime 将为 0。这意味着,如果你使用 Time.deltaTime 来控制旋转和位移等,那Time.timeScale = 0 也将使这些物体停止运动。

Time.timeScale 还会影响 Time.time 的时间,比如 Time.timeScale = 2 的话,那么 Time.time 的增长速度也会变成 2 倍速度。如果你想取到游戏的实际时间,那么使用Time.timeSinceLevelLoad 就可以,前提是必须在 Awake() 方法以后再取,如果在 Awake() 方法里面取 Time.realtimeSinceStartup 会取出一个错误的值,在 Start 方法里面取的话就正常了。如果游戏暂停以后想在暂停界面上继续播放一些不受 Time.timeScale 影响的动画,那么我们就需要用到 Time.realtimeSinceStartup。

update不受时间冻结影响,例如如下的代码:

    void Start()
    {
        Time.timeScale=0;
    }

    private void FixedUpdate()
    {
        transform.position = new Vector3(transform.position.x+0.01f,
            transform.position.y,
            transform.position.z);
    }

    void Update()
    {
        transform.position = new Vector3(transform.position.x,
                transform.position.y + 0.01f,
                transform.position.z);
    }

物体会往y坐标走

 

GameObject 游戏物体

activeSelf   自身是否是被激活状态

activeInHierarchy 物体在场景中是否被显示(即若这个值为true,则物体以及父物体都是被激活的)

hierarchy:统治集团、层次体系

BroadcastMessage 向GameObject与它的子物体发送消息

SendMessageUpwards 向GameObject与它的子物体发送消息

SendMessage 向GameObject发送消息

这三个发送消息的方法的参数都是别的方法名,当有游戏物体接收到消息,他们就会看自己有没有叫这个方法名的方法,若有,则会调用自身的这个方法

 

 

 

 

 

构造方法

Instantiate 实例化一个对象

CreatePrimitive 创建一个带有基本网格渲染器和相应碰撞器的游戏物体。

//在场景中创建一个平面,球体
GameObject.CreatePrimitive(PrimitiveType.Plane);
GameObject.CreatePrimitive(PrimitiveType.Cube);

 

 

Mathf

Deg2Rad   把角度换成弧度的变量,等价 (PI * 2)/360 。

Infinity 无穷大

Clamp 限制一个值在两个数之间

ClosestPowerOfTwo 返回距离value最近的2的次方数。

Lerp  按照数字t在from到to之间插值。

t是夹在 [0……1]之间,当t = 0时,返回from,当t = 1时,返回to。当t = 0.5 返回from和to的平均数。
注意第三个参数t,不要理解为t时间内从from到to,平时比如移动位移的时候或做旋转的时候,可以把t作为时间单位,但是一定要注意这个t的值是从0到1范围。
搭配好协程就可以有平滑移动的效果
    IEnumerator CameraMove(Vector3 po, Vector3 qua)
    {
        yield return new WaitForSeconds(0.5f);
        Vector3 TargetPosition = po;
        Quaternion TargetRotation = Quaternion.Euler(qua);
        while (MainCamera.transform.position != TargetPosition && Quaternion.Angle(MainCamera.transform.rotation, TargetRotation) >= 1)
        {
            //基于浮点数t返回a到b之间的插值,t限制在0~1之间。当t = 0返回from,当t = 1 返回to。当t = 0.5 返回from和to的平均值。
            MainCamera.transform.position = new Vector3(Mathf.Lerp(MainCamera.transform.position.x, po.x + 0.1f, Time.deltaTime),
                                                    Mathf.Lerp(MainCamera.transform.position.y, po.y + 0.1f, Time.deltaTime),
                                                    Mathf.Lerp(MainCamera.transform.position.z, po.z + 0.1f, Time.deltaTime));
            MainCamera.transform.rotation = Quaternion.Slerp(MainCamera.transform.rotation, TargetRotation, Time.deltaTime);
            yield return 0;
        }
    }

 

LerpAngle 角度的插值,和 lerp 道理一样

MoveTowards 向方向移动

作用是将当前值current移向目标target。(对Vector3是沿两点间直线)
maxDistanceDelta就是每次移动的最大长度。
返回值是当current值加上maxDistanceDelta的值,如果这个值超过了target,返回的就是target的值。

PingPong  乒乓效果,循环往复

Round  四舍五入

SmoothDamp   平滑阻尼

static function SmoothDamp (current : Vector3target : Vector3ref currentVelocity : Vector3smoothTime : float, maxSpeed : float = Mathf.InfinitydeltaTime : float = Time.deltaTime)

各参数含义:

1.current 当前物体位置

2.target 目标物体位置

3.ref currentVelocity 当前速度,这个值由你每次调用这个函数时被修改(注:ref 关键字指参数按引用传递, 按引用传递的效果是,对所调用方法中参数进行的任何更改都反映在调用方法中。)

4.smoothTime 到达目标的时间,较小的值将快速到达目标

5.maxSpeed 所允许的最大速度,默认无穷大

6.deltaTime 自上次调用这个函数的时间,默认为Time.deltaTime

 

Input

GetKey 按下键返回true

GetKeyDown  当用户按下指定名称的按键时的那一帧返回true

GetKeyUp  在用户释放给定名字的按键的那一帧返回true

GetAxis 参数为Horizontal 则按下左右箭头分别返回-1、1,不按则返回0;Vertical对应上下箭头

 

Random

Range 返回一个在最大最小之间的随机数(包括最大最小)

 

 

Camera

main 静态属性,第一个标签是MainCamera的物体

ScreenToWorldPoint:从屏幕空间到世界空间的变化位置。屏幕空间以像素定义。屏幕的左下为(0,0);右上是(pixelWidth,pixelHeight),Z的位置是以世界单位衡量的到相机的距离。

WorldToScreenPoint:从世界空间到屏幕空间变换位置。屏幕空间以像素定义,屏幕左下为(0,0),右上是(pixelWidth,pixelHeight),Z的位置是以世界单位衡量的到相机的距离。

 

 

Application

dataPath 数据路径(比如我windows下:F:/Unity3D/test/Assets)

CaptureScreenshot  截图

更多Application的路径变量

 

 

SceneManager

LoadScene 加载场景通过Build Settings里的名字或者变量

LoadSceneAsync 异步加载场景(一般大场景会用到)

sync:同步

async:异步

1、AsyncOperation 在你不主动设置AllowSceneActivation = false的情况下,isDown会随着progress的增长(从0增长到1)自动变成true,所以会自动跳转场景;

2、如果你不想让场景进行自动跳转,你就需要在异步加载时设置allowSceneActivation = false,这会使场景不进行自动跳转,原因是isDown在allowSceneActivation = false 的情况下 永远不会为true,并且此时的aysncOperation.progress也最多可以加载到0.9(90%),当你允许你的场景跳转时(设置allowSceneActivation = true),progress加载最后的10%,直到progress = 1, isDown此时自动变为true,异步加载完成,实现场景跳转。

跟多可以看这里——异步跳转场景

另外在编辑器中进度条不会显示中间过程,这是因为 编辑器下只能同步加载,虽然调用的异步的接口,所以进度条会从0到100

 

 

Vector2

vactor是一个结构体,不是一个类

官网参考

down 下的意思,对应坐标(0,-1)

其他上、右、左都是一样的道理

magnitude 向量长度

normalized 单位向量(方向不变,长度变成1)

x x坐标

我们知道在transform.position.x中,不能对x属性直接复制,position是一个Vector2类型的属性,Vctor2是一个结构体,所以position是一个结构体,结构体是一个值类型,值类型在方法传递的时只传递值的副本

Normalize  自身单位化,将自身变成单位向量

 


常见API以及Unity技巧补充

监听UGUI的事件

  • 直接给按钮等UGUI控件拖拽添加注册响应方法即可
  • 通过代码实现UGUI控件的事件监听

通过给button组件添加监听器来实现点击组件会触发方法,示例代码如下:

    private void Start()
    {
        button.GetComponent<Button>().onClick.AddListener(this.buttonOnClick);            
    }

    void buttonOnClick() {
        print("Button on click!");
    }
  • 通过实现接口

实现接口这个方法不像前两种方法那么自由了,官方文档奉上

这些就是我们可以实现的接口,每一个接口都对应了一个事件

上图的pointer代表鼠标指针

示例。我们给一个UI图片添加了一个脚本文件,内容如下:

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

public class UIEventManager : MonoBehaviour, IPointerDownHandler
{
    public void OnPointerDown(PointerEventData eventData)
    {
        print("IPointerDown");
    }
}

然后在Scene中点击这个UI图片,就出现了命令行提示

另外注意,一定要保证UI身上的Raycast Target 是勾选上的。

 

实现UI拖拽

还是上面的那个官方网页,那些接口中有一些比较牛逼的东西,就是Drag接口,可以实现UI的拖拽

下面给出UI拖拽的示例代码:

public class Scence2Task2DragControl : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
{
    private RectTransform rectTransform;
    private void Start()
    {
        rectTransform = GetComponent<RectTransform>();
    }
    public void OnBeginDrag(UnityEngine.EventSystems.PointerEventData eventData)
    {
        print("开始拖拽" + GetComponent<Text>().text);
    }
    public void OnDrag(UnityEngine.EventSystems.PointerEventData eventData)
    {
        Vector3 pos;
        //鼠标屏幕位置转换世界位置
        RectTransformUtility.ScreenPointToWorldPointInRectangle(
            rectTransform, eventData.position,
            eventData.enterEventCamera, out pos);
        rectTransform.position = pos;

        print(eventData.pointerPressRaycast.gameObject.name);
    }
    public void OnEndDrag(UnityEngine.EventSystems.PointerEventData eventData)
    {
        print("结束拖拽" + GetComponent<Text>().text);
    }
}

如果你要检测拖拽指针位置是否在某UI上,建议使用如下代码,IPointerEnterHandler 亲测不好用……

//鼠标在某rect范围内
if (RectTransformUtility.RectangleContainsScreenPoint(_transform, Input.mousePosition))

 

 

 

UnityWebRequest

这个类是代替以前的WWW类,可以访问网络资源(Unity爬虫?)

官方文档奉上

下面有一个爬取图片的示例

using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
using UnityEngine.UI;

public class UIEventManager : MonoBehaviour {

    public Image image;

    void Start() {
        StartCoroutine(GetText());
    }
    IEnumerator GetText() {
        using (UnityWebRequest uwr = UnityWebRequestTexture.GetTexture("https://马赛克.com/gp=0.jpg")) {
            yield return uwr.SendWebRequest();
            if (uwr.isNetworkError || uwr.isHttpError) {
                Debug.Log(uwr.error);
            } else {
                // Get downloaded asset bundle 
                image.material.mainTexture = DownloadHandlerTexture.GetContent(uwr);
            }
        }
    }
}

更多使用请参考Unity2019对于弃用WWW加载方式后的新替代的API的UnityWebRequest的使用

触摸事件

这些事件主要值针对于移动端

通过touch对象来操纵,这个我们以后学安卓再深究

官方文档奉上

 

 

 


 

这些先记录这么多吧,后续会不断更新

 

 

商业转载 请联系作者获得授权,非商业转载 请标明出处,谢谢

 

是的,我就是计算机界的枭雄!