常用API
打印函数
print & Debug.log功能一致
print("这节开始我们正式进入API课程的学习");
Debug.Log("UnityAPI常用方法类与组件");
//1.测试
Calculate();
//2.检错
Debug.Log("2+3的计算开始了");
int a = 1;
Debug.Log("a赋值完成,具体值是:"+a);
int b = 3;
Debug.Log("b赋值完成,具体值是:"+b);
int num = a + b;
Debug.Log("2+3="+num);
Debug.LogWarning("这是一个警告!");
Debug.LogError("这里有报错!");
gameobject要执行行为,必须继承Monobehavior类
脚本生命周期
private void Reset()
{
//1.调用情况
//此函数只能在编辑器模式下(不运行)调用。
//2.调用时间,次数与作用
//当脚本第一次挂载到对象或者使用了Reset命令之后调用,
//来初始化脚本的各个属性,Reset最常用于在检视面板中提供良好的默认值。
Debug.Log("调用了Reset方法");
Debug.Log("攻击值重置为默认值");
}
private void Awake()
{
//1.调用情况
//a.在加载场景时初始化包含脚本的激活状态的GameObject时
//b.GameObject从非激活转变为激活状态
//c.在初始化使用Instantiate创建的GameObject之后
//2.调用时间,次数与作用
//在脚本实例的生存期内,Unity 仅调用 Awake 一次。脚本的生存期持续到包含它的场景被卸载为止。
//Unity 调用每个GameObject的Awake的顺序是不确定的,人为干涉(即设计)来保证程序的正确性和稳定性
// Awake 来代替构造函数进行初始化,在Unity这里,组件的初始化不使用构造函数
Debug.log("调用了Awake方法");
attackValue = 1;
}
游戏物体失活时,每次激活都会调用OnEable()方法
//a.游戏物体被激活
//b.脚本组件被激活
private void OnEnable()
{
//1.调用情况
//a.游戏物体被激活
//b.脚本组件被激活
//2.调用时间,次数与作用
//每次游戏物体或者脚本被激活都会调用一次
//重复赋值 变为初始状态
Debug.Log("调用了OnEnable方法");
currentHP = 100;
Debug.Log("当前血量为:"+currentHP);
attackValue = 2;
}
void Start()
{
//1.调用情况
//a.游戏物体被激活
//b.脚本组件被激活
//2.调用时间,次数与作用
//在脚本实例激活时在第一帧的Update之前被调用
//后于Awake执行,方便控制逻辑的前后调用顺序
Debug.Log("调用了Start方法");
attackValue = 3;
}
每帧调用
void Update()
{
//1.调用情况
//a.游戏物体被激活
//b.脚本组件被激活
//2.调用时间,次数与作用
//每帧调用,是最常用函数,每秒调用60次左右(根据当前电脑的的性能和状态)
//实时更新数据,接受输入数据
Debug.Log("调用了Update方法");
}
LateUpdate( )涉及一些物理逻辑,延时逻辑相对于Update( )
private void LateUpdate()
{
//1.调用情况
//a.游戏物体被激活
//b.脚本组件被激活
//2.调用时间,次数与作用
//LateUpdate在调用所有Update函数后调用,每秒调用60次左右,安排脚本的执行顺序
//比如摄像机跟随,一定是人物先移动了,摄像机才会跟随
Debug.Log("调用了LateUpdate方法");
}
OnDisable()
//b.脚本组件被禁用
//c.游戏物体被销毁
private void OnDisable()
{
//1.调用情况
//a.游戏物体被禁用
//b.脚本组件被禁用
//c.游戏物体被销毁
//2.调用时间,次数与作用
//满足调用情况时即时调用一次,用于一些对象的状态重置,资源回收与清理
Debug.Log("调用了OnDisable方法");
}
void OnApplicatoinQuit()
{
//1.调用情况
//a.在程序退出之前所有的游戏对象都会调用这个函数
//b.在编辑器中会在用户终止播放模式时调用
//c.在网页视图关闭时调用
//2.调用时间,次数与作用
//满足调用情况时即时调用一次,用于处理一些游戏退出后的逻辑
Debug.Log("OnApplicationQuit");
}
void OnDestroy()
{
//1.调用情况
//a.场景或游戏结束
//b.停止播放模式将终止应用程序
//c.在网页视图关闭时调用
//d.当前脚本被移除
//e.当前脚本挂载到的游戏物体被删除
//2.调用时间,次数与作用
//满足调用情况时即时调用一次,用于一些游戏物体的销毁
Debug.Log("OnDestroy");
}
GameObject属性
//1.创建方式
public GameObject grisGo;
// Start is called before the first frame update
void Start()
{
GameObject go = new GameObject("MY");//动态创建
//预制体初始化
GameObject.Instantiate(grisGo);
Debug.Log("当前脚本挂载到的游戏物体名称是:" + gameObject.name);
//GameObject.Instantiate;
//GameObject.CreatePrimitive;
Debug.Log("当前游戏物体标签是:" + gameObject.tag);
Debug.Log("当前游戏物体层级是:" + gameObject.layer);
//游戏物体的激活失活
gameObject.SetActive(true);
Debug.Log("当前游戏物体的状态是:" + gameObject.activeInHierarchy);
Debug.Log("当前游戏物体的状态是:" + gameObject.activeSelf);
//有引用
//对自己 this.gameObject
//对其他游戏物体
Debug.Log(grisGo.activeSelf);//gris游戏物体的状态
//b.通过标签查找
GameObject mainCameraGo = GameObject.FindGameObjectWithTag("MainCamera");
Debug.Log("mainCamera游戏物体的名字是:" + mainCameraGo.name);
//c.通过类型查找
No2_EventFunction no2_EventFunction = GameObject.FindObjectOfType<No2_EventFunction>();
Debug.Log("no2_EventFunction游戏物体的名字是:" + no2_EventFunction.name);
//d.多数查找与获取
GameObject[] enemyGos = GameObject.FindGameObjectsWithTag("Enemy");
for (int i = 0; i < enemyGos.Length; i++)
{
Debug.Log("查找到的敌人游戏物体名称是:" + enemyGos[i].name);
}
BoxCollider[] colliders = GameObject.FindObjectsOfType<BoxCollider>();
Debug.Log("--------------------------------------------------");
for (int i = 0; i < colliders.Length; i++)
{
Debug.Log("查找到的敌人碰撞器名称是:" + colliders[i].name);
}
}
MonoBehaviour
//MonoBehaviour派生自组件脚本,因此组件脚本所有的公有,保护的属性,成员变量
//方法等功能,MonoBehaviour也都有,继承mono之后这类可以挂载到游戏物体上
Debug.Log("No4_MonoBehaviour组件的激活状态是:"+this.enabled);
Debug.Log("No4_MonoBehaviour组件挂载的对象名称是:" + this.name);
Debug.Log("No4_MonoBehaviour组件挂载的标签名称是:" + this.tag);
Debug.Log("No4_MonoBehaviour组件是否已激活并启用Behaviour:" + this.isActiveAndEnabled);
print("Trigger");
//Destroy();
//FindObjectsOfType();
//Instantiate();
继承关系父->子;
Object->Component->behavior->Monobehavior
Component的查找与获取
Component的查找与获取
public GameObject enemyGos;
void start()
{
No5_Component no5_Component = gameObject.GetComponent<No5_Component>();
No2_EventFunction no2_EventFunction = gameObject.GetComponent<No2_EventFunction>();
//Debug.Log(no2_EventFunction);
//Debug.Log(no2_EventFunction.attackValue);
Debug.Log(no5_Component.testValue);
//获得Gris小姐姐的组件
GameObject grisGo = GameObject.Find("Gris");//Find(Object名称)
Debug.Log(grisGo.GetComponent<SpriteRenderer>());
Debug.Log(enemyGos.GetComponentInChildren<BoxCollider>());
Debug.Log(enemyGos.GetComponentsInChildren<BoxCollider>());//获取子对象方法
Debug.Log(enemyGos.GetComponentInParent<BoxCollider>());//获取父对象方法
//b.通过其他组件查找
SpriteRenderer sr= grisGo.GetComponent<SpriteRenderer>();
sr.GetComponent<Transform>();
this.GetComponent<Transform>();
}
Component.Transform()类
void Start()
{
//场景中的每个对象都有一个变换组件。 它用于存储和操作对象的位置、旋转和缩放。
//1.访问与获取
Debug.Log(this.transform);
Debug.Log(grisGo.transform);
Transform grisTrans = grisGo.transform;
//2.成员变量
Debug.Log("Gris变换组件所挂载的游戏物体名字是grisTrans.name:" + grisTrans.name);
Debug.Log("Gris变换组件所挂载的游戏物体引用是grisTrans.gameObject:" + grisTrans.gameObject);
Debug.Log("Gris下的子对象(指Transform)grisTrans.childCount的个数是:" + grisTrans.childCount);
Debug.Log("Gris世界空间中的坐标位置是grisTrans.position:" + grisTrans.position);
Debug.Log("Gris以四元数形式表示的旋转是:"+grisTrans.rotation);
Debug.Log("Gris以欧拉角形式表示的旋转(Rotation以度数为单位)是"+grisTrans.eulerAngles);
Debug.Log("Gris的父级Transform是grisTrans.parent:" + grisTrans.parent);
Debug.Log("Gris相对于父对象的位置坐标是grisTrans.localPosition:" + grisTrans.localPosition);
Debug.Log("Gris相对于父对象以四元数形式表示的旋转是 grisTrans.localRotation:" + grisTrans.localRotation);
Debug.Log("Gris相对于父对象以欧拉角形式表示的旋转(以度数为单位) grisTrans.localEulerAngles是:" + grisTrans.localEulerAngles);
Debug.Log("Gris相对于父对象的变换缩放是grisTrans.localScale" + grisTrans.localScale);
Debug.Log("Gris的自身坐标正前方(Z轴正方向)grisTrans.forward是:" + grisTrans.forward);
Debug.Log("Gris的自身坐标正右方(X轴正方向)grisTrans.right是:" + grisTrans.right);
Debug.Log("Gris的自身坐标正上方(Y轴正方向)grisTrans.up是:" + grisTrans.up);
//共有方法
//3.查找
Debug.Log("当前脚本挂载的游戏对象下的叫Gris的子对象身上的Transform组件是:" + transform.Find("Gris"));
Debug.Log("当前脚本挂载的游戏对象下的第一个(0号索引)子对象的Transform引用是:" + transform.GetChild(0));
Debug.Log("Gris当前在此父对象同级里所在的索引位置:" + grisTrans.GetSiblingIndex());
静态方法
Transform.Destroy(grisTrans.gameObject);
//transform.findobjectoftype();
//transform.instantiate();
}
Vector2
Y轴up正向,X轴right正向
void Start()
{
静态变量
print(Vector2.down);
print(Vector2.up);//Y轴正方向
print(Vector2.left);
print(Vector2.right);//X轴正方向
print(Vector2.one);
print(Vector2.zero);
//构造函数
Vector2 v2 = new Vector2(2, 2);
print("V2向量是:" + v2);
//成员变量
print("V2向量的模长是:" + v2.magnitude);
print("V2向量的模长的平方是:" + v2.sqrMagnitude);
print("V2向量单位化之后是:" + v2.normalized);//转化为长度为1的
print("V2向量的XY值分别是:" + v2.x + "," + v2.y);
print("V2向量的XY值分别是(使用索引器形式访问):" + v2[0] + "," + v2[1]);
//公共函数
bool equal = v2.Equals(new Vector2(1, 1));
print("V2向量与向量(1,1)是否相等?" + equal);
Vector2 v2E = new Vector2(1, 3);
bool equalv2E = v2E.Equals(new Vector2(3, 1));
print("v2E向量与向量(3,1)是否相等?" + equal);
print("V2向量是:" + v2);
print("V2向量的单位化向量是:" + v2.normalized + "但是V2向量的值还是:" + v2);
v2.Normalize();
print("V2向量是:" + v2);
v2.Set(5, 9);
print("V2向量是:" + v2);
transform.position = v2;
//transform.position.x = 4;//不可以单独赋值某一个值,比如x
//结论1:用属性和方法返回的结构体是不能修改其字段的
MyStruct myStruct = new MyStruct();//A
myStruct.name = "Trigger";
myStruct.age = 100;
//结论2:直接访问公有的结构体是可以修改其字段的
MyStruct yourStruct = myStruct;//B
yourStruct.name = "小可爱";
yourStruct.age = 18;
print("原本的结构体对象名字是:" + myStruct.name);
print("修改后的结构体对象名字是:" + yourStruct.name);
MyClass myClass = new MyClass();//A
myClass.name = "Trigger";
myClass.age = 100;
MyClass yourClass = myClass;//B跟A是同一块内存空间
yourClass.name = "小阔爱";
yourClass.age = 18;
print("原本的结构体对象名字是:" + myClass.name);
print("修改后的结构体对象名字是:" + yourClass.name);
//总结导致这个问题的原因:
//1,Transform中的position是属性(换成方法也一样,因为属性的实现本质上还是方法)而不是公有字段
//2,position的类型是Vector的,而Vector是Struct类型
//3,Struct之间的赋值是拷贝而不是引用
修改位置
transform.position = new Vector2(3, 3);
Vector2 vector2 = transform.position;
vector2.x = 2;
transform.position = vector2;
静态函数
Vector2 va = new Vector2(1, 0);
Vector2 vb = new Vector2(0, 1);
Debug.Log("从va指向vb方向计算的无符号夹角是:" + Vector2.Angle(va, vb));
print("va点与vb点之间的距离是:" + Vector2.Distance(va, vb));
print("向量va与向量vb的点积是:" + Vector2.Dot(va, vb));
print("向量va和向量vb在各个方向上的最大分量组成的新向量是:" + Vector2.Max(va, vb));
print("向量va和向量vb在各个方向上的最小分量组成的新向量是:" + Vector2.Min(va, vb));
//具体得到的新向量的结果的计算公式是:a+(b-a)*t
print("va向vb按照0.5的比例进行线性插值变化之后的结果是" + Vector2.Lerp(va, vb, 0.5f));
print("va向vb按照参数为-1的形式进行(无限制)线性插值变化之后的结果是" + Vector2.LerpUnclamped(va, vb, -1));
float maxDistance = 0.5f;
print("将点va以最大距离不超过maxDistance为移动步频移向vb" + Vector2.MoveTowards(va, vb, maxDistance));
print("va和vb之间的有符号角度(以度为单位,逆时针为正)是" + Vector2.SignedAngle(va, vb));
print("vb和va之间的有符号角度(以度为单位,逆时针为正)是" + Vector2.SignedAngle(vb, va));
print("va和vb在各个方向上的分量相乘得到的新向量是:" + Vector2.Scale(va, vb));
Vector2 currentVelocity = new Vector2(1, 0);
print(Vector2.SmoothDamp(va, vb, ref currentVelocity, 0.1f));
//运算符
print("va加上vb向量是:" + (va + vb));
print("va减去vb向量是:" + (va - vb));
print("va减去vb向量是:" + va * 10);
print("va与vb是同一个向量吗" + (va == vb));
}
用户输入输出Input
void Update()
{
//连续检测(移动)
print("当前玩家输入的水平方向的轴值是:" + Input.GetAxis("Horizontal"));
print("当前玩家输入的垂直方向的轴值是:" + Input.GetAxis("Vertical"));
print("当前玩家输入的水平方向的边界轴值是:" + Input.GetAxisRaw("Horizontal"));
print("当前玩家输入的垂直方向的边界轴值是:" + Input.GetAxisRaw("Vertical"));
print("当前玩家鼠标水平移动增量是:" + Input.GetAxis("Mouse X"));
print("当前玩家鼠标垂直移动增量是:" + Input.GetAxis("Mouse Y"));
//连续检测(事件)
if (Input.GetButton("Fire1"))
{
print("当前玩家正在使用武器1进行攻击!");
}
if (Input.GetButton("Fire2"))
{
print("当前玩家正在使用武器2进行攻击!");
}
if (Input.GetButton("RecoverSkill"))
{
print("当前玩家使用了恢复技能回血!");
}
//间隔检测(事件)
if (Input.GetButtonDown("Jump"))
{
print("当前玩家按下跳跃键");
}
if (Input.GetButtonUp("Squat"))
{
print("当前玩家松开蹲下建");
}
if (Input.GetKeyDown(KeyCode.Q))
{
print("当前玩家按下Q键");
}
if (Input.anyKeyDown)
{
print("当前玩家按下了任意一个按键,游戏开始");
}
if (Input.GetMouseButton(0))
{
print("当前玩家按住鼠标左键");
}
if (Input.GetMouseButtonDown(1))
{
print("当前玩家按下鼠标右键");
}
if (Input.GetMouseButtonUp(2))
{
print("当前玩家抬起鼠标中键(从按下状态松开滚轮)");
}
}
GameObject之间的消息传递
外部类的引用
void Start()
{
//仅发送消息给自己(以及身上的其他MonoBehaviour对象)
gameObject.SendMessage("GetMsg");
SendMessage("GetSrcMsg","Trigger");
SendMessage("GetTestMsg",SendMessageOptions.DontRequireReceiver);
//广播消息(向下发,所有子对象包括自己)
BroadcastMessage("GetMsg");
//向上发送消息(父对象包含自己)
SendMessageUpwards("GetMsg");
}
void Update()
{
}
public void GetMsg()
{
print("测试对象本身接收到消息了");
}
public void GetSrcMsg(string str)
{
print("测试对象本身接收到的消息为:"+str);
}
动画制作
构建Animation / Animator / Sprites folder
- Sprites包含了各种状态对应的图片族(24帧)
- Animator下建立Animator Controller
图片导入sprites后,inspector窗口修改TYPE为Sprite ( 2D and UI ),Mode 设置为Single,
Gameobject添加Animator组件。挂载Controller.
全选拖入Gameobject(project窗口),快速生成Animation
创建2D 人物 任务23
任务 69 学会改motion 测试动画
Parameters设置一些人物属性,
void Start()
{
animator.Play("New Animation_idle");
animator.speed = 3;
animator.SetFloat("Speed", 3);//设置参数初值
animator.SetBool("IsDead", false);
animator.SetInteger("HP", 100);
print("当前速度参数的值是:" + animator.GetFloat("Speed"));
}
配置状态机
crossFade() 动画过渡
void Update()
{
if(Input.GetKeyDown(KeyCode.W))
{
animator.CrossFade("New Animation_walk", 1); //动画过度(,参数2为动画融合的归一化时间)
}
if (Input.GetKeyDown(KeyCode.W))
{
animator.CrossFadeInFixedTime("New Animation_walk", 0.5f); //动画过度(,秒为单位的淡入淡出)
}
}
Time()类
void Update()
{
print(Time.deltaTime + ",完成上一帧所用的时间(以秒为单位)");
print(Time.fixedDeltaTime + ",执行物理或者其他固定帧率更新的时间间隔");
print(Time.fixedTime + ",自游戏启动以来的总时间(以物理或者其他固定帧率更新的时间间隔累计计算的)");
print(Time.time + ",游戏开始以来的总时间");
print(Time.realtimeSinceStartup + ",游戏开始以来的实际时间");
print(Time.smoothDeltaTime + ",经过平滑处理的Time.deltaTime的时间");
print(Time.timeScale + ",时间流逝的标度,可以用来慢放动作");
print(Time.timeSinceLevelLoad + ",自加载上一个关卡以来的时间");
}
Math()类
void Start()
{
//静态变量
print(Mathf.Deg2Rad + ",度到弧度换算常量");
print(Mathf.Rad2Deg + ",弧度到度换算常量");
print(Mathf.Infinity + "正无穷大的表示形式");
print(Mathf.NegativeInfinity + "负无穷大的表示形式");
print(Mathf.PI);
//静态函数
print(Mathf.Abs(-1.2f) + ",-1.2的绝对值");
print(Mathf.Acos(1) + ",1(以弧度为单位)的反余弦");
print(Mathf.Floor(2.74f) + ",小于或等于2.74的最大整数");
print(Mathf.FloorToInt(2.74f) + ",小于或等于2.74的最大整数");
//a+(b-a)*t
print(Mathf.Lerp(1, 2, 0.5f) + ",a和b按参数t进行线性插值");
print(Mathf.LerpUnclamped(1, 2, -0.5f) + ",a和b按参数t进行线性插值");
}
Random()类
void Start()
{
//静态变量
print(Random.rotation + ",随机出的旋转数是(以四元数形式表示)");
print(Random.rotation.eulerAngles + ",四元数转换成欧拉角");
print(Quaternion.Euler(Random.rotation.eulerAngles) + ",欧拉角转四元数");
print(Random.value + ",随机出[0,1]之间的浮点数");
print(Random.insideUnitCircle + ",在(-1,-1)~(1,1)范围内随机生成的一个vector2");
print(Random.state+",当前随机数生成器的状态");
//静态函数
print(Random.Range(0,4)+",在区间[0,4)(整形重载包含左Min,不包含右Max)产生的随机数");
print(Random.Range(0, 4f) + ",在区间[0,4)(浮点形重载包含左Min,包含右Max)产生的随机数");
Random.InitState(1);
print(Random.Range(0,4f)+",设置完随机数状态之后在[0,4]区间内生成的随机数");
}
鼠标行为检测的回调事件
- 为GameObject挂载碰撞器
private void OnMouseDown()
{
print("在Gris身上按下了鼠标");
}
private void OnMouseUp()
{
print("在Gris身上按下的鼠标抬起了");
}
private void OnMouseDrag()
{
print("在Gris身上用鼠标进行了拖拽操作");
}
private void OnMouseEnter()
{
print("鼠标移入了Gris");
}
private void OnMouseExit()
{
print("鼠标移出了Gris");
}
private void OnMouseOver()
{
print("鼠标悬停在了Gris上方");
}
private void OnMouseUpAsButton()
{
print("鼠标在Gris身上松开了");
}
协程原理与作用
- 用法:
延时调用:比如10秒生成一波小兵
异步操作:多开一个线程完成一些繁琐的工作,本线程继续进行
(无法确定协程之间执行的相互顺序)
//用法和用途(1.延时调用,2.和其他逻辑一起协同执行
//(比如一些很耗时的工作,在这个协程中执行异步操作,比如下载文件,加载文件等)
public Animator animator;
public int grisCount;
private int grisNum;
void Start()
{
//协程的启动
StartCoroutine("ChangeState");//字符串传参启动对应于字符串传参终止
StartCoroutine(ChangeState());
IEnumerator ie = ChangeState();
StartCoroutine(ie);
// 协程的停止
StopCoroutine("ChangeState");
// 无法停止协程
StopCoroutine(ChangeState());
StopCoroutine(ie);
StopAllCoroutines();
StartCoroutine("CreateGris");
}
void Update()
{
}
IEnumerator ChangeState()
{
//暂停几秒(协程挂起)走到这里休眠2s
yield return new WaitForSeconds(2);
animator.Play("Walk");
yield return new WaitForSeconds(3);
animator.Play("Run");
//等待一帧 yield return n(n是任意数字)
yield return null;
yield return 100000;
print("转换成Run状态了");
//在本帧帧末执行以下逻辑
yield return new WaitForEndOfFrame();
}
IEnumerator CreateGris()
{
StartCoroutine(SetCreateCount(5));
while (true)
{
if (grisNum>=grisCount)
{
yield break;
}
Instantiate(animator.gameObject);
grisNum++;
yield return new WaitForSeconds(2);
}
}
IEnumerator SetCreateCount(int num)
{
grisCount =num;
yield return null;
}
Invoke实现延时调用
public GameObject grisGo;
void Start()
{
//调用
//Invoke("CreateGris",3);
InvokeRepeating("CreateGris",1,1);
//停止
CancelInvoke("CreateGris");
//CancelInvoke();
InvokeRepeating("Test",1,1);
}
void Update()
{
print(IsInvoking("CreateGris"));
print(IsInvoking());
}
private void CreateGris()
{
Instantiate(grisGo);
}
private void Test()
{
}
刚体的成员属性
实现物体移动的三种方式:
- 使用Movepostion()方法实现移动
- 对刚体施加力的方式,实现移动,AddForce()
- 直接作用刚体的速度,rb.Velocity = Vector2.right * moveSpeed;
使用刚体让游戏物体旋转
rb.MoveRotation(rb.rotation+angle*Time.fixedDeltaTime);
transform.Translate()实现移动
//移动
//0.第二个参数不填(实际情况按自身坐标系移动,space.self)
grisGo.transform.Translate(Vector2.left * moveSpeed);//自身坐标系
grisGo.transform.Translate(-grisGo.transform.right * moveSpeed);//世界坐标系
//1.第一个参数按世界坐标系移动,第二个参数指定世界坐标系(实际情况按世界坐标系移动)
grisGo.transform.Translate(Vector2.left * moveSpeed, Space.World);
//2.第一个参数按世界坐标系移动,第二个参数指定自身坐标系(实际情况按自身坐标系移动)
grisGo.transform.Translate(Vector2.left * moveSpeed, Space.Self);
//3.第一个参数按自身坐标系移动,第二个参数指定世界坐标系(实际情况按自身坐标系移动)
grisGo.transform.Translate(-grisGo.transform.right * moveSpeed, Space.World);
//4.第一个参数按自身坐标系移动,第二个参数指定自身坐标系(实际情况按世界坐标系移动)(一般不使用)
grisGo.transform.Translate(-grisGo.transform.right * moveSpeed, Space.Self);
//旋转
grisGo.transform.Rotate(new Vector3(0, 0, 1));
grisGo.transform.Rotate(Vector3.forward, 1);