什么是API?——预先设置好的编程接口
事件函数及常用脚本
事件函数的执行顺序
具体可参考:docs.unity.cn/cn/current/Manual/ExecutionOrder.html
*函数前加fix和不加fix的区别(如Fixupdate和update的区别):加fix后调用执行的次数固定,不会再受到电脑硬件影响。正常来说,电脑的一帧受硬件本身的影响,在0.02s左右上下浮动,update调用的次数就是0.02s左右一次,而fixupdate受客观时间影响,固定0.0166...667s执行一次
常用的事件函数
Time类
CaptureFrameRate 设置帧速率并截图
deltaTime 当前帧所占用时间
//在update方法中1s向前移动1m
//正常而言,update时间是0.02s(1/50 s)上下,直接写移动方法后物体相当于0.02s左右移动1m
cube.Translate(Vector3.forward/50f);
cube.Translate(Vector3.forward * Time.deltaTime); //更为精确的写法
fixedDeltaTime 固定的一帧所占用的时间
realtimeSinceStartup 从游戏开始运行到现在所用时间(不受暂停等操作影响)
//测试哪个方法更占用性能
public int runCount = 10000; //一条代码运行多次放大时间测试性能
void Method1()
{
int i = 1+2;
}
float time1 = Time.realtimeSinceStartup;
for(int i=0;i<runCount;i++)
{
Method1();
}
float time2 = Time.realtimeSinceStartup;
Debug(time2-time1); //该方法执行10000次所用时间
//-----------------------------------------------------------
void Method2()
{
int j = 1*2;
}
float time3 = Time.realtimeSinceStartup;
for(int i=0;i<runCount;i++)
{
Method2();
}
float time4 = Time.realtimeSinceStartup;
Debug(time4-time3);
//通过比较这两个差值,得出哪个方法更加占用性能
time 游戏实际运行时间
fixedTime 游戏实际运行时间,值和time接近
timeSinceLevelLoad Scene在加载后游戏运行的时间,如果进入下一个scene将重新计时
frameCount 帧数
timeScale 让游戏暂停/加速/减速
//游戏暂停
Time.timeScale = 0;
//影响Time.deltaTime的系数 可以理解为 Time.deltaTime *=Time.timeScale
//注意:物体需要*Time.deltaTime才会暂停
//0.5倍速
Time.timeScale = 0.5;
创建游戏物体
方法一:
GameObject go = new GameObject(); //括号内可加字符串如“Cube”,则创建一个方块
方法二:
//根据prefab或场景中的游戏物体创建
public GameObject prefab;
GameObject.Instantiate(prefab);
方法三:
GameObject.CreatePrimitive(PrimitiveType.Plane);
//该方法可创建U3D中基本形状
为游戏物体添加组件
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Plane);
go.AddComponent<Rigidbody>();
go.AddComponent<API01EventFunction>(); //可以添加自定义脚本
判断游戏物体是否被禁用
xxx.activeInHierachy //判断场景中的物体是否被禁用,返回bool值
//物体会受到父物体是否被禁用的影响,如果父物体被禁用,则该物体也不显示,此时返回false
xxx.activeSelf //判断自身是否激活,即使父物体被禁用,如果物体本身未被禁用则返回true
Unity常用类
游戏——>场景——>游戏物体——>组件
一个游戏由多个场景组成
一个场景由多个游戏物体组成
一个游戏物体由多个组件组成
UnityEngine.Object(基类)——>GameObject
——>Component
UnityEngine.Object
属性
name 返回名称
方法
Destroy();
DontDestroyOnLoad(); 将物体从A场景带入B场景时不销毁游戏物体
FindObjectOfType<>(); 在游戏场景中找到第一个含有该组件物体下的第一个该组件
Light light = FindObjectOfType<Light>();
light.enabled = false;
FindObjectsOfType<>(); 找到游戏场景中的所有该组件并返回一个数组
Transform[] ts = FindObjectsOfType<Transform>();
//不查找未激活的游戏物体
Instantiate 更多参数可查找API
(Object original,Vector3 position,Quaternion rotation,Transform parent);
创建的物体,位置,旋转,哪个父物体下
(Object original,Transform parent);
不指定位置旋转,放于parent下;
(Object original,Transform parent,bool InstantiateInWorldSpace)
最后一个参数为是否世界坐标系,如果为True则是,False则会根据父物体的坐标位置和旋转改变自身的位置和旋转。
GameObject类与Component类中的公共方法
AddComponent();
CompareTag();
SetActive();
BroadcastMessage();
public GameObject target;
target.BroadcastMessage("Attack");
//其下所有子物体及其下所有脚本如有如下方法:
void Attack()
{
}
//则被调用
SendMessage();
SendMessageUpwards(); 向其自身及其所有祖先发送消息
GetComponent
GetComponents
GetComponentInChildren
GetComponentsInChildren
GetComponentInParent
GetComponentsInParent
GameObject类
属性
activeHierachy
activeSelf
xxx.activeInHierachy //判断场景中的物体是否被禁用,返回bool值
//物体会受到父物体是否被禁用的影响,如果父物体被禁用,则该物体也不显示,此时返回false
xxx.activeSelf //判断自身是否激活,即使父物体被禁用,如果物体本身未被禁用则返回true
layer
scene
tag
方法
CreatePrimitive();
Find(); 根据名字查找物体
GameObject go = GameObject.Find("Main Camera");
go.SetActive(false);
FindGameObjectWithTag 根据标签,查找到第一个游戏物体
FindGameObjectsWithTag 根据标签,查找所有游戏物体
GameObject[] gos = GameObject.FindGameObjectsWithTag("Main Camera");
gos[0].SetActive(false);
Component类——>MonoBehaviour类
属性
isActiveAndEnabled 判断组件是否激活
enabled 激活/禁用
tag
gameObject 当前游戏物体
transform
name
方法
print(); 静态方法,输出日志
Invoke("xxx",int x); 调用某方法,在x秒后(x这个参数可以不写)
CancelInvoke("xxx") 取消Invoke,如不指定参数则取消所有Invoke
InvokeRepeating 重复调用
InvokeRepeating("Attack",4,2);
//4s后重复调用Attack方法,每2s调用一次
//不用放于Update()中!!!
IsInvoking 判断某方法是否正在调用
如果执行的是一个普通方法,那么会等这个普通方法执行完,然后再继续执行。如果调用的是一个协程方法,那么调用完协程方法后,不会等这个方法执行完就继续向下执行了。
1.协程方法不会阻塞当前方法的运行
2.协程方法自身可以进行暂停
StartCoroutine
public GameObject cube;
//1.返回值是IEnumerator
IEnumerator ChangeColor()
{
Cube.GetComponent<MeshRenderer>().material.color = color.blue;
yield return null;
}
//2.返回参数的时候用yield return
//协程暂停
yield return new WaitForSeconds(3); //等待3s
//3.调用协程方法:StartCoroutine(method());
void Start()
{
StartCoroutine(ChangeColor());
}
//通过协程实现颜色的渐变
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
StartCoroutine(Fade());
}
IEnumerator Fade()
{
for(float i=0;i<=1;i+=0.1f) //颜色变化的范围从0到1
{
cube.GetComponent<MeshRenderer>().material.color = new Color(i,i,i);
//Color的三个参数代表RGB
yield return new WaitForSeconds(0.1f); //动画暂停0.1s
}
}
StopAllCoroutines
StopCoroutine("xxx"); 停止一个指定的协程
注意:StartCoroutine 与 StopCoroutine 调用的参数需相同
如字符串则同为字符串,如为IEnumerator则同为IEnumerator
IEnumerator ie;
ie=Fade();
StartCoroutine(ie);
StopCoroutine(ie);
//or
StartCoroutine("Fade");
StopCoroutine("Fade");
Mouse相关方法
可搜索API OnMouseXXX
注意:如果物体标记为Trigger,则保证physics窗口中QueriesHitTriggers勾选
Mathf类
静态变量
PI
Deg2Rad 度数变为弧度
Rad2Deg 弧度变为度数
Epsilon 最小单位小数
任意值+Epsilon=任意值本身
任意值-Epsilon=值本身
0+Epsilon=0
0-Epsilon=0
Infinity 无穷大
NegativeInfinity 无穷小
静态方法
Abs 绝对值
Ceil 向上取整,返回float
CeilToInt 向上取整,返回Int
Clamp(float value,float min,float max); 将值限定在一个范围内
value<min 返回min
value>max 返回max
min<value<max 返回value
public Transform cube;
cube.position = new Vector3(Mathf.Clamp(Time.time,1.0f,3.0f),0,0)
//物体小于1s时静止,1-3s时运动,大于3s时静止
//简化代码:
private int hp=100;
void TakeDamage()
{
int hp-=9;
//if(hp<0)hp=0;
hp=Mathf.Clamp(hp,0,100);
}
Clamp01(float value) 将min设置为0,max设置为1
ClosetPowerOfTwo(int value) 取得和value最近的2的次方数
DeltaAngle(float current,float target) 计算两角度间的最小距离
Exp(float power) e^power次方
Floor(float f) 向下取整,返回float
FloorToInt(float f) 向下取整,返回int
Max 返回一个最大值
Min 返回一个最小值
Pow(float f,float p); f^p次方
Sqrt(float f) 根号f
Lerp(float a,float b,float t)
0<=t<=1,通过系数t取a与b之间的值,t=0时返回a,t=1时返回b
//减速运动 无限接近目标
float x = cube.position.x;
float newx = Mathf.Lerp(x,10,0.1f);
cube.position = new Vector3(newx,0,0);
MoveTowards(float current,float target,float maxDelta); 与Lerp相似,但是为匀速,即每次current+maxDelta,但小于target
1s运行1m
float x = cube.position.x;
float newx = Mathf.MoveTowards(x,10,Time.deltaTime);
//Time.deltaTime*speed 可以控制运行的速度
cube.position = new Vector3(newx,0,0);
PingPong(float t,float length); 在0~length之间来回变化,t为系数控制来回
0<=t<=length时 返回t
length<t<=2*length 返回2*length-t
...
形成往复
//来回运动
cube.position = new Vector3(Mathf.PingPong(Time.time,10),0,0)
//每秒运行1m
Random类
属性
Value 0.0~1.0之间的随机值
state 随机数种子
rotation 四元数随机值
insideUnitCircle 在一个物体附近单位圆范围内随机生成一个三维position
insideUnitSphere 在一个物体附近单位球体范围内随机生成一个三维position
方法
Range() Random.Range(4,10)随机生成4~9之间的数
InitState(int seed) 初始化随机数种子
Quaternion类 四元数
输出旋转角
print(cube.eulerAngles); //欧拉角
print(cube.rotation); //四元数
赋值
cube.eulerAngles = new Vector3(10,0,0);
//四元数赋值不可写为:
//cube.rotation = new Vector3(10,0,0);
//欧拉角不可赋值给四元数
//应使用欧拉角与四元数的转换方法Euler
cube.rotation = Quaternion.Euler(new Vector3(10,0,0));
获取四元数的欧拉角
cube.rotation.eulerAngles;
创建一个由A望向B的四元数方向
//使用 LookRotation(Vector3 forward,Vector3 upwards);
public Transform player;
public Transform enemy;
Vector3 dir = enemy.position - player.position;
player.rotation = Quaternion.LookRotation(dir);
//返回前方向到dir的旋转
Lerp & Slerp(一般多用Slerp)
由当前旋转转到目标旋转
Quaternion target = Quaternion.LookRotation(dir);
player.rotation = Quaternion.Slerp(player.rotation,target,Time.deltaTime);
//Slerp比Lerp更准确,更平滑
Input类
属性
anyKey 任意键
anyKeyDown 任意键按下后
mousePosition 返回鼠标在屏幕上的位置
方法
GetKeyXXX 监听键盘事件 具体方法见API文档
GetKey 有哪些键盘事件可在API中搜索:Conventional Game Input
GetMouseXXX 监听鼠标事件 具体方法见API文档
GetButtonDown("XXX") 其中,XXX为虚拟按钮,可在InputManager(Edit->Project Settings-> Input)窗口查看有哪些虚拟按键并设置
GetAxis("XXX") 返回一个虚拟按键输入后的渐变值
//控制移动
cube.Translate(Vector3.right * Time.deltaTime*Input.GetAxis("Horizental"));
//其中,Horizental为虚拟按键,当按下a或d时,返回一个-1到0或0到1的变化值
GetAxisRaw("XXX") 返回一个虚拟按键输入后的确定值(如a就为-1,d就为1)
Vector2 结构体(Vector3 类似不重复)
属性
x
y
//取得二维向量的x与y
//1.
a.x a.y
//2
a[0] a[1]
magnitude 长度
normalized 单位化
sqrMagnitude 未开根的长度
关于Vector2值的修改:
transform.position = new Vector3(3,3,3);
//transform.position.x = 3 错误写法
//应为:
Vector3 pos = transform.position;
pos.x = 10;
transform.position = pos;
//向量为结构体,是值类型,应当整体赋值
方法
Normalize(); 单位化
更多见API
Rigidbody类
属性
centerOfMass 取得中心点
position 位置,性能比Transform.position好
rotation 旋转,性能比Transform.rotation好
更多见API
方法
MovePosition 移动会更加平滑
playerRgd.MovePosition(playerRgd.transform.position + Vector3.forward*Time.deltaTime );
AddForce(Vector3) 施加力
Camera类
main 获取mainCamera
private Camera mainCamera;
mainCamera = Camera.main;
鼠标发射射线,检测鼠标是否停留在物体上
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition)
//该方法生成一个由屏幕中心点到某物体中心的一条射线
RaycastHit hit;
bool isCollider = Physics.Raycast(ray,out hit);
if(isCollider)
Debug.Log(hit.collider);
Application类
属性
datapath 路径,Assets文件夹
persistentDataPath
streamingAssetsPath 资源文件,U3D内命名为StreamingAssets的文件夹不会被编译,会原样输出至打包目录
temporaryCachePath 临时目录
方法
Application.OpenURL() 打开网络
Application.Quit() 退出
Application.CaptureScreenShot() 路径名
SceneManager类
属性
sceneCount 场景总数量
方法
LoadScene() 加载场景
Using UnityEngine.SceneManagement;
SceneManager.LoadScene(1); //1为场景编号,在编译界面调整顺序
//or
SceneManager.LoadScene("02-MenuScene");//Scene的名称
GetActiveScene() 得到当前场景
LoadSceneAsync() 异步加载
GetSceneAt() 获取已加载的场景信息
射线检测
Physics.Raycast
Physics.RaycastAll 射线会穿透检测所有的物体
检测正前方是否有敌人
void update()
{
Ray ray = new Ray(transform.position+transform.forward,transform.forward);
//其中transform.position + transform.forward是将射线发射点前置一些,防止射线与自身碰撞
bool isCollider = Physics.Raycast(ray);
Debug.Log(isCollider);
}
//其中Physics.Raycast()有众多重载方法,更多可见API
Physics.Raycast(ray,out hit); //可通过hit获取碰撞物体
//hit拥有的属性: hit.point位置 hit.collider物体的碰撞器
Physics.Raycast(ray,Length,LayerMask);//LayerMask:射线只检测Layermask的层
LayerMask.GetMask("Enemy");//获取Enemy层
UGUI方法
实现事件监听的三个方法:
1.直接拖拽脚本
2.代码添加
Using UnityEngine.UI;
//button
public GameObject btnGameComponent;
btnGameComponent.GetComponent<Button>().onClick.AddListener(this.ButtonOnClick);
void ButtonOnClick()
{
Debug.Log("ButtonOnClick")
}
//slider(dropdown,toggole都类似)
public GameObject sliderGameObject;
sliderGameObject.GetComponent<Slider>().onValueChanged.AddListener(this.OnSliderChanged);
void OnSliderChanged(float value)//dropdown为int32,toggle为bool
{
Debug.Log("SliderChanged:"+value);
}
3.接口实现
using UnityEngine EventSystems;
using UnityEngine.UI;
public class UIEventManager:MonoBehaviour,IPointerDownHandler
{
public void OnPointDown(PointerEventData eventData)
//eventData为封装数据,命名要求相同,不用在意里面写了什么
{
Debug.Log("xxx");
}
}
//启动并按下按钮后启动日志
//其他更多接口:
IPointerClickHandler //点击后出发
IPointerUpHandler //抬起
IPointerEnterHandler //进入
IPointerExitHandler //移出
//还有拖拽相关的接口IDragXXX查API
WWW类
载入网络图片,见API
Touches类 触摸检测
见API,建议使用easyTouch插件做触摸检测
Camera类
属性
main 得到main camera
方法
ScreenPointToRay() 将一个屏幕坐标转换为射线
//发射并显示鼠标位置的一条射线
private Camera camera;
void Start()
{
camera = Camera.main;
}
void update()
{
Ray ray = Camera.ScreenPoinToRay(Input.mousePosition);
Debug.DrawRay(ray.origin,ray.direction);
}
//检测鼠标位置是否有物体
private Camera camera;
void Start()
{
camera = Camera.main;
}
void update()
{
Ray ray = Camera.ScreenPoinToRay(Input.mousePosition);
RaycastHit hit;
bool isCollider = Physics.Raycast(ray,out hit);
Debug.Log(hit.collider)//不用hit.collider.gameObject是预防出现空指针
}
Character Controller类
属性
bool isGrounded 判断是否在地面上
方法
OnControllerColliderHit 返回碰撞到的collider,会自动多次调用
SimpleMove 控制移动
控制移动
public float speed=3;
private CharacterController cc;
cc=GetComponent<CharacterController>();
float h=Input.GetAxis("Horizental");
float v=Input.GetAxis("Vertical");
cc.SimpleMove(new Vector3(h,0,v)*speed);
//or
cc.Move(new Vector3(h,0,v)*speed*Time.deltaTime);
Mesh类
//将一个方体的Mesh变为球体
public Mesh mesh //u3d中赋值为球体
GetComponent<MeshFilter>.mesh = mesh;
Material类
//颜色渐变
private Material mat;
mat = GetComponent<MeshRenderer>().material;
mat.color = Color.Lerp(mat.color,Color.red,Time.deltaTime);
Animator类
speed 设置状态机速度
GetCurrentAnimatorClipInfo 获取当前状态
AudioSource类
//播放声音
GetComponent<AudioSource>().play();
粒子系统
ParticleSystem.MainModule.main = smokePuff.GetComponent<ParticleSystem>().main;