Alt+鼠标左键–旋转视图
Alt+鼠标右键–放大缩小视图
利用标签,可以将对象分为几类,以便让脚本仅在触碰到正确的对象时才能触发操作;没有标签,就无法区分对象。
3.物体发生碰撞的必要条件:两个物体都必须带有碰撞器(Collider),其中一个物体还必须带有Rigidbody刚体或者charactercontroller组件。
4.unity中游戏是由多个scene来组成的 5.Comeponent组件该组件定义了包含它们的游戏对象的行为,是每个游戏对象的功能单元。
6.Transform 组件Transform 变换组件用于存储游戏对象的位置、旋转、缩放和父子化状态,因此非常重要。游戏对象始终附加一个变换组件,无法删除变换组件或创建没有变换组件的游戏对象。
变换组件的位置、旋转和缩放值是相对于变换组件的父项测量的。如果变换组件没有父项,则按照世界空间来测量属性。
Inspector 中任何子游戏对象的 Transform 值都是相对于父项 Transform 值显示的结果。这些值称为“局部坐标”。
在文档中,被称为“最重要的概念”,原因也很简单,即“万物皆对象”。Unity 中,游戏由场景组成,而场景中的任何元素,都是游戏对象。游戏对象是 Unity 中的基础对象,表示角色、道具和景物。它们本身并没有取得多大作为,但它们充当组件的容器,而组件可实现功能。游戏对象始终附加一个变换组件(表示位置和方向),并且无法删除此组件。
8.子对象中的坐标是相对于父对象而言的,并不是世界坐标 9.关于刚体(3D)Rigidbody中的 Is Kinematic启用 Is Kinematic,则刚体对象将不会被物理引擎驱动,只能通过变换 (Transform) 对其进行操作。
9.关于球体碰撞器Sphere Collider使用时,需要使作用物体被包括在该碰撞器中,即用“编辑碰撞器”选项来改变大小。
10.关于预制体Prefabs(又称预制件)更多信息见链接预制件
11.unity打印在控制台Debug.Log();
12.精灵 Sprite 是 Unity 中 2D 素材的默认存在形式,是 Unity 中的 2D 图形对象。在 2D 游戏中,使用 2D 素材的过程:PNG(JPG 等)----> Sprite ----> GameObject
13.关于Transform- 2D 游戏中,没有 Z 轴来表示深度,只有 X 轴和 Y 轴,以中心点为原点(0,0),左 x 负,右 x 正,上 y 正,下 y 负
- Unity 中,通过游戏对象的 Transform 组件,可以获取该对象在场景中的位置 Position,并通过更改 Transform 组件 Position 的值,可以更改其位置,依据的坐标轴就是上面所描述的 2D 坐标轴
- transform.position用来获取当前对象的位置
1.见链接
2.见链接
方法1:(不太推荐)
方法2:(推荐)
时间和帧率
18.瓦片地图1.参考文档:
文档1
文档2
1.透视图指的是有深度、距离感的图,一般要三维中的深度轴来表现场景的深度,而二维游戏中没有这个深度,只能通过前后来仿造深度效果,称为“伪透视图”。
先前通过调整瓦片的 Order in Layer 属性来解决了瓦片地图的排序问题,但并非总是希望一个游戏对象在另一个游戏对象之上,比如,在同一个瓦片地图中,
玩家角色在一个物体之前(比如一棵树)时,应该是玩家遮挡树,而玩家移动到树后时,应该是树遮挡玩家,这就需要“伪造”透视图(两物体的图层顺序相同时才生效)。
在 2D 游戏中,场景里的 “前后” 是由 Y 轴决定的,需要让 Unity 根据游戏对象的 y 坐标来绘制游戏对象Y 轴 y 坐标值越小,越靠前,
应该遮挡 y 坐标值较大的游戏对象,也就是 y 坐标较小的游戏对象后绘制,就会位于上层在游戏中,如果要设置 2D 伪透视试图,需要在项目设置中进行更改:
Edit > Project Settings > Graphics > Camera Settings > Transparency Sort Mode = Custom Axis > Transparency Sort Axis x = 0 / y = 1 / z = 0
例如:
2.轴心,可在Sprite Editor中进行修改(在游戏中,为了更好地玩家交互,可以将有些物体的轴心设置为底部中间位置,即x:0.5,y:0)20.两物体碰撞时发生抖动解决方法代码
1.代码如图:
2.具体解决方法可见链接
两物体碰撞时发生抖动问题
(1)
(2)
1.具体使用方法如代码所示:
//注:currentHealth、maxHealth均为自定义的整形数值 currentHealth=Mathf.Clamp(currentHealth,0,maxHealth);//限制currentHealth的值在0和maxHealth之间, 如果currentHealth小于0,返回0;如果currentHealth大于maxHealth,返回maxHealth;否则返回value24.unity中触发器
1.触发器(Trigger),是一种特殊类型的碰撞体,触发器不会阻止移动,但是物理系统仍会检查角色是否与碰撞器发生碰撞,比如当角色进入触发器时,你将收到一条消息,以便可以处理该事件。
总之一句话就是:触发器碰撞体只检测碰撞,不组织移动;碰撞时,可接受到消息,根据需求添加相关处理代码
2.触发器相关函数():
(1)当绑定着碰撞器的游戏对象进入触发器区域的时候,会运行触发器对象上的MonoBeavior中的OnTriggerEnter()函数;
(2)当其处在触发器区域的时候会运行OnTriggerStay()函数,每帧调用一次OnTriggerStay()函数;注:OnTriggerStay()函数每帧调用一次
(3)当其离开触发器区域的时候会运行OnTriggerExit()函数;
详细可见链接
26.面向对象c#等语言中,数据成员变量都应尽可能地设置为私有,只能通过当前类的方法或属性进行访问。 27.c#中属性1.属性的定义
public int MyIntProp{
set{
//给属性设置值的时候,就会调用属性中的set块,因此可以在set块中通过value访问到我们所设置的值。
}
get{
//当取得属性的值得时候,就会调用属性中的get块,因此get块需要返回值,其返回值类型就是属性的类型。
}
}
2.具体用法举例:
namespace Ch05Ex03
{
class D
{
private double _nameField = 3.14;
public double NameFild
{
set
{
_nameField = value > 100 ? 100 : value; //执行计算
}
get
{
return _nameField;
}
}
}
class Program
{
static void Main(string[] args)
{
D myD = new D();
myD.NameFild = 200; //给访问器中的字段赋值
WriteLine(myD.NameFild); //输出赋值后的字段的值
ReadKey();
}
}
}
应用场所举例:出于保护数据的原因,设置封装了一个private类型的数据成员number,但是要在该类外调用并修改此数据成员numbe,此时便可以在number所属的类内定义一个public类型的属性,并在该属性内部实现对数据成员number的修改,然后就可以在类外调用该属性并修改number的值了。
28.Unity中Update函数每帧调用一次,而FIxedUpdate函数每0.02秒调用一次 29.unity2D 动画(文档参考链接) 30.Unity 使用 Quaternion 类来存储游戏对象的三维方向,也使用它们来描述从一个方向到另一个方向的相对旋转。Quaternion.identity就是指Quaternion(0,0,0,0) 31.Mathf.Approximately用于比较两个浮点值,如果它们相似,则返回 true。 32.在3D中让玩家角色走动并使朝向旋转的代码:using System.Collections; using System.Collections.Generic; using UnityEngine; ///33.从代码中学习/// /// public class PlayerMovement : MonoBehaviour { //TODO: //1.获取玩家输入,在场景中移动玩家角色游戏对象 //2.移动时,除了位置之外position,还需要考虑转动rotation //3.需要将动画也考虑进去 Vector3 m_Movement; //创建一个3D矢量,来表示玩家角色的移动 //获取用户输入方向 float horizontal;//x轴方向 float vertical;//z轴方向 Rigidbody m_Rigidbody;//创建一个刚体对象 Animator m_Animator;//创建一个animator组件对象 Quaternion m_Rotation=Quaternion.identity;//用四元数对象m_Rotation来表示游戏对象中的旋转,Quaternion.identity就是指Quaternion(0,0,0,0), public float turnSpeed = 20.0f;//旋转速度 private void Start() { m_Animator = GetComponent();//获取游戏对象的动画器组件 m_Rigidbody = GetComponent ();//获取游戏对象的刚体组件 } private void Update() { //获取用户输入方向 horizontal = Input.GetAxis("Horizontal");//获取x轴方向输入,Input.GetAxis("Horizontal")代表X轴方向移动 vertical = Input.GetAxis("Vertical");//获取z轴方向,Input.GetAxis("Vertical")代表Z轴方向移动 } private void FixedUpdate() { m_Movement.Set(horizontal, 0.0f, vertical);//设置该3D矢量的坐标,参数为用户输入的三维矢量 m_Movement.Normalize();//将该向量的长度设置为1 bool hasHorizontal = !Mathf.Approximately(horizontal, 0.0f);//判断是否有横向移动 bool hasVertical = !Mathf.Approximately(vertical, 0.0f);//判断是否有纵向移动;Mathf.Approximately用于比较两个浮点值,如果它们相似,则返回 true bool isWalking = hasHorizontal || hasVertical;//横向或者纵向有一个移动,玩家角色便是处于移动状态 m_Animator.SetBool("IsWalking", isWalking);//将变量传递给动画管理器 Vector3 desiredForward = Vector3.RotateTowards(transform.forward, m_Movement, turnSpeed * Time.deltaTime, 0f);//用三维矢量表示转向后的玩家角色朝向; m_Rotation = Quaternion.LookRotation(desiredForward);//设置四元数对象的值 } private void OnAnimatorMove()//当动画播放引发根移动时执行 { m_Rigidbody.MovePosition(m_Rigidbody.position + m_Movement * m_Animator.deltaPosition.magnitude);//使用从用户输入获取到的三维矢量作为移动方向,使用动画中每次0.02秒移动的距离作为距离来移动 m_Rigidbody.MoveRotation(m_Rotation);//旋转游戏对象 } }
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RubyController : MonoBehaviour
{
public GameObject projectTilePrefab;//声明一个公开的游戏对象,用来获取子弹的预制件
bool isInvincible;//设置玩家是否处于无敌状态
public float timeInvincible=2.0f;//设置玩家无敌状态的时间间隔
float invincibleTimer;//定义变量,进行无敌时间的计时,无敌时间计时器
public int maxHealth=5;//生命值的上限(最大生命值)
private int currentHealth;//目前生命值
AudioSource audioSource;//声明音频源对象,用来后期进行音频播放控制
public AudioClip throwCogClip;//声明一个公开的音频剪辑变量,用来在unity inspector中,挂接要播放的音频剪辑
public float throwCogSoundVol = 1.0f;//播放音频的音量大小
public AudioClip playerHitClip;//声明一个公开的音频剪辑变量,用来在unity inspector中,挂接要播放的音频剪辑
public float playerHitSoundVol = 1.0f;//播放音频的音量大小
public int health//设置当前生命值的属性health;在c#中支持面向对象程序设计中的封装概念,对数据成员的保护;
{
get{return currentHealth;}
}
public float speed=0.1f;
Rigidbody2D rigidbody2D1;
float horizontal;
float vertical;
Animator animator;//声明一个动画管理者组件对象
//与机器人相比,Ruby可以站着不动,当站着不动时,Move X和Move Y均为0,这时状态机就没法获取Ruby静止时的朝向,所以需要手动设置一个
Vector2 lookDirection=new Vector2(1,0);//创建一个二维矢量,用来存储Ruby静止不移动时的方向(即面向的方向)
Vector2 move;//移动二维矢量
void Start()//系统函数,游戏刚开始运行时调用
{
rigidbody2D1=GetComponent();//获取该物体的刚体组件
currentHealth=maxHealth;//在游戏刚开始时设置当前生命值为最大生命值(即满血状态)
animator =GetComponent();//获取组件对象
audioSource=GetComponent();//获取声音源组件对象
}
void Update()//系统函数,每帧调用一次
{
horizontal=Input.GetAxis("Horizontal");
vertical=Input.GetAxis("Vertical");
//判断是否处于无敌状态,来进行计时器的更改
if(isInvincible)//如果无敌,则进入倒计时
{
invincibleTimer-=Time.deltaTime;//每次Update减去一帧所消耗的时间
if(invincibleTimer<0)//如果计时器中时间用完
{
isInvincible=false;//取消无敌状态
}
}
move=new Vector2(horizontal,vertical);//创建一个二维矢量对象来表示Ruby移动的数据信息
//如果move中的x/y不为0,表示正在运动
//将ruby面向方向设置为移动方向
//停止移动,保持以前方向,所以这个if结构用于转向时重新赋值面朝方向
if(!Mathf.Approximately(move.x,0.0f)||!Mathf.Approximately(move.y,0.0f))
{
lookDirection.Set(move.x,move.y);
//使向量长度为1,可以将此方法成为向量的”归一化”方法
//通常用在表示方向,而非位置的向量上
//因为blender tree中表示方向的参数取值范围是-1.0到1.0
//所以一般用向量作为Animator.SetFloat的参数时,一般要对向量先进行”归一化处理”
lookDirection.Normalize();
}
//传递ruby面朝方向给blend tree
animator.SetFloat("Look X",lookDirection.x);
animator.SetFloat("Look Y",lookDirection.y);
//传递ruby速度给blend tree
//矢量的magniute属性,用来返回矢量的长度
animator.SetFloat("Speed",move.magnitude);
//添加发射子弹的逻辑
if(Input.GetKeyDown(KeyCode.C) || Input.GetAxis("Fire1")!=0)//玩家按下键盘上的C键,或者按下发射键(左ctrl或鼠标左键)发射子弹
{
Launch();//调用下边定义好的发射子弹函数
}
if (Input.GetKeyDown(KeyCode.X))//使用x键激活射线投射
{
//创建一个射线投射碰撞对象,来接收射线投射碰撞信息
//射线投射使用的是Physics2D.Raycast方法
//参数1:射线投射的位置
//参数2:投射方向
//参数3:投射距离
//参数4:射线生效的层
RaycastHit2D hit = Physics2D.Raycast(rigidbody2D1.position + Vector2.up * 0.2f, lookDirection,1.5f,LayerMask.GetMask("NPC"));
if (hit.collider != null)
{
Debug.Log($"射线投射碰撞到的对象是:{hit.collider.gameObject}");
NonPlayerCharacter npc=hit.collider.GetComponent();//创建NPC代码组件
if (npc != null)
{
npc.DisplayDialog();//调用NPC组件的显示对话框的方法
}
}
}
}
void FixedUpdate()//系统函数,固定时间间隔(默认为0.02秒)执行一次
{
Vector2 position=transform.position;//获取当前对象的位置
position.x=position.x+speed*horizontal*Time.deltaTime;
position.y=position.y+speed*vertical*Time.deltaTime;
transform.position=position;
}
public void changeHealth(int amount)//自定义函数,改变玩家当前生命值
{
if(amount<0)//如果玩家要减血
{
if(isInvincible)//如果处在无敌状态,则无需进行加血或掉血的操作,跳出当前changeHealth方法
{
return;
}
isInvincible=true;//当不是无敌状态时,重置无敌状态为真
invincibleTimer=timeInvincible;//重置无敌时间
animator.SetTrigger("Hit");//播放受伤动画
PlaySound(playerHitClip, playerHitSoundVol);//播放受伤掉血的音频
}
currentHealth=Mathf.Clamp(currentHealth+amount,0,maxHealth);//此句代码的意思是:限制玩家当前生命值的范围为0-最大生命值。//函数解析:限制currentHealth+amount的值在0和maxHealth之间, 如果currentHealth+amount小于0,返回0;如果currentHealth+amount大于maxHealth,返回maxHealth;否则返回value
//Debug.Log("当前生命值:"+currentHealth+"/"+maxHealth);//控制台输出生命值
UiHealthBar.Instance.SetValue(currentHealth/(float)maxHealth);
}
void Launch()//玩家发射子弹
{
GameObject projectTileObject=Instantiate(projectTilePrefab,rigidbody2D1.position+Vector2.up*0.5f,Quaternion.identity);//Instantiate为实例化一个游戏对象
ProjectTile projecttile=projectTileObject.GetComponent();//获取子弹游戏对象的脚本组件对象(ProjectTile是自定义的一个类,在ProjectTile脚本中)
projecttile.Launch(lookDirection,300);//通过脚本对象调用子弹移动的方法,第一个参数是移动的方向,取得是玩家面朝的方向;第二个参数是力,如果想要速度快些,可以加大
animator.SetTrigger("Launch");
PlaySound(throwCogClip, throwCogSoundVol);//播放发射子弹的音频
}
public void PlaySound(AudioClip audioClip,float soundVol)//新增一个公有方法,一经调用,会播放指定的音频剪辑
{
audioSource.PlayOneShot(audioClip, soundVol);//调用音频源的PlayOneShot方法,播放指定的音频
}
//添加Ruby投掷齿轮发出的声音,以及受到伤害时发出的声音
}
34.从代码中学习
using System.Collections; using System.Collections.Generic; using UnityEngine; ///35.从代码中学习/// /// public class ProjectTile : MonoBehaviour//子弹预制件脚本 { Rigidbody2D rigidbody2d; //声明刚体对象 void Awake()//在创建对象时(调用 Instantiate 时)就会立即调用 Awake函数 { rigidbody2d=GetComponent();//获取刚体对象实例 } public void Launch(Vector2 direction,float force)//把当前子弹发射出去 { rigidbody2d.AddForce(direction*force);//通过刚体对象调用物理系统的AddForce方法,给游戏对象施加一个力,使其移动 } private void OnCollisionEnter2D(Collision2D other)//OnCollisionEnter2D为2D碰撞事件(是系统函数) { EnemyController2 enemyController2=other.collider.GetComponent ();//获取齿轮飞弹碰到的机器人对象的脚本组件 if(enemyController2!=null) { enemyController2.Fix(); } Debug.Log($"齿轮子弹碰撞到了:{other.gameObject}");//&为c#中的一种输出格式 Destroy(gameObject);//碰撞后,销毁子弹游戏对象 } private void Update() { if(transform.position.magnitude>50.0f)//如果没有碰到碰撞体的齿轮,在飞行距离超过50单位后,自动销毁 { Destroy(gameObject); } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using TMPro; ///36.从代码中学习/// /// public class NonPlayerCharacter : MonoBehaviour//控制对话框的显示 { public float displayTime = 4.0f;//默认显示时间是0.4秒 public GameObject dialogBox;//获取对话框游戏对象 float timerDisplay;//计时器,用来倒计时文本框显示的时间 public GameObject dlgTxtProGameObject;//创建一个游戏对象,来获取TMP控件 TextMeshProUGUI _tmTxtBox;//创建游戏组件累对象 int _currentPage = 1;//设置变量存储当前页数 int _totalPages;//设置变量,用来存储总页数 private void Start() { dialogBox.SetActive(false);//游戏一开始时,不显示对话框 timerDisplay = -1.0f;//设置计时器刚开始不可用 _tmTxtBox=dlgTxtProGameObject.GetComponent();//获取对话框TMP组件 } private void Update()//每帧调用一次 { _totalPages = _tmTxtBox.textInfo.pageCount;//获取对话框组件中,对话文字的总页数(start方法中获取不到) if (timerDisplay >= 0.0f)//如果倒计时没结束 { if (Input.GetKeyUp(KeyCode.Space))//如果按下键盘的空格键 { if (_currentPage < _totalPages)//如果没到最后一页,就向后翻页 { _currentPage++; }else { _currentPage = 1; } _tmTxtBox.pageToDisplay = _currentPage;//文本框中显示当前页 } timerDisplay -= Time.deltaTime;//倒计时 }else { dialogBox.SetActive(false);//否则,倒计时结束,让对话框隐藏 } } public void DisplayDialog()//NPC说话方法 { timerDisplay = displayTime;//重置计时器 dialogBox.SetActive (true);//显示对话框 } }
using System.Collections; using System.Collections.Generic; using UnityEngine; ///37. UnityEditor.EditorApplication.isPlaying = false;//在untiy编译器中,停止游戏的运行;Application.Quit();//结束当前游戏(该函数在打包发布时才能生效) 38.人物寻迹行走代码/// /// public class EnemyController2 : MonoBehaviour { public float speed;//移动速度 public bool Vertical;//是否垂直移动,如果是true就沿y轴移动,如果是false就按x轴移动 Rigidbody2D rigidbody2d;//声明刚体对象 public float changeTime=3.0f;//朝一个方向移动的总时间 private float timer;//计时器 int direction=1;//移动方向 Animator animator;//动画器组件 bool broked=true;//设定一个bool值,初始值true代表机器人刚开始是”坏”的 public ParticleSystem smokeEffect;//开放一个属性用来获取烟雾属性,方便用代码来操作 void Start() { rigidbody2d=GetComponent();//获取刚体组件 timer=changeTime; animator=GetComponent ();//获取当前机器人对象的动画器组件 } void Update()//每帧调用一次 { if(!broked)//如果已经修复机器人,则直接退出update方法 { return; } timer-=Time.deltaTime; if(timer<0) { direction=-direction;//调头 timer=changeTime; } } private void FixedUpdate()//移动刚体(该函数默认0.02秒执行一次) { if(!broked)//如果已经修复机器人,则直接退出update方法 { return; } Vector2 position=rigidbody2d.position;//获取当前对象所在位置 if(Vertical)//纵向移动,沿着y轴移动 { position.y+=Time.deltaTime*speed*direction;//Time.deltaTime是每帧的时间间隔,float类型 animator.SetFloat("Move X",0); animator.SetFloat("Move Y",direction); }else//横向移动,沿着x轴移动 { position.x+=Time.deltaTime*speed*direction; animator.SetFloat("Move X",direction); animator.SetFloat("Move Y",0); } rigidbody2d.MovePosition(position);//刚体进行移动 } //用OnCollisionEnter2D添加对玩家的伤害 private void OnCollisionEnter2D(Collision2D other)//刚体碰撞事件 { RubyController rubyController=other.gameObject.GetComponent ();//获取玩家角色对象 if(rubyController!=null) { rubyController.changeHealth(-1);//如果玩家碰到该敌人,就使玩家血量减1 } } public void Fix()//修复机器人的犯法 { broked=false;//更改状态为修复,让机器人不会再被碰撞 rigidbody2d.simulated=false;//刚体对象取消物理引擎效果 animator.SetTrigger("Fixed"); // Destroy(smokeEffect);//摧毁该机器人头顶的烟雾特效 smokeEffect.Stop();//特效停止产生新的粒子,原有已经生成的粒子会正常走完它的生命周期 } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; ///39.人物在3D场景中行走并实现旋转、动画的代码/// /// public class WayPointPatrol : MonoBehaviour { NavMeshAgent navMeshAgent;//获取当前游戏对象的导航网格代理组件 public Transform[] waypoints;//路径点数组 int m_CurrentWaypointIndex;//当前的路径点索引数,范围是0到waypoints.length -1 void Start() { navMeshAgent = GetComponent();//获取组件对象 navMeshAgent.SetDestination(waypoints[0].position);//设置导航组件导航路径的起始点位 } void Update()//每次刷新,都要获取下一个路径点,并通过算法,让路径点循环往复 { if (navMeshAgent.remainingDistance < navMeshAgent.stoppingDistance) //当前游戏对象到指定的路径点的距离,如果小于最终停止距离 { m_CurrentWaypointIndex = (m_CurrentWaypointIndex + 1) % waypoints.Length;//获取下一个路径点在数组中的索引,并通过取余%实现循环效果 navMeshAgent.SetDestination(waypoints[m_CurrentWaypointIndex].position);//设置新的导航位置 } } }
using System.Collections; using System.Collections.Generic; using UnityEngine; ///40.监测人物进入视野代码/// /// public class PlayerMovement : MonoBehaviour { //TODO: //1.获取玩家输入,在场景中移动玩家角色游戏对象 //2.移动时,除了位置之外position,还需要考虑转动rotation //3.需要将动画也考虑进去 Vector3 m_Movement; //创建一个3D矢量,来表示玩家角色的移动 //获取用户输入方向 float horizontal;//x轴方向 float vertical;//z轴方向 Rigidbody m_Rigidbody;//创建一个刚体对象 Animator m_Animator;//创建一个animator组件对象 Quaternion m_Rotation=Quaternion.identity;//用四元数对象m_Rotation来表示游戏对象中的旋转,Quaternion.identity就是指Quaternion(0,0,0,0), public float turnSpeed = 20.0f;//旋转速度 AudioSource m_AudioSource;//声明音源组件对象 private void Start() { m_Animator = GetComponent();//获取游戏对象的动画器组件 m_Rigidbody = GetComponent ();//获取游戏对象的刚体组件 m_AudioSource= GetComponent ();//获取当前对象音源组件 } private void Update() { //获取用户输入方向 horizontal = Input.GetAxis("Horizontal");//获取x轴方向输入,Input.GetAxis("Horizontal")代表X轴方向移动 vertical = Input.GetAxis("Vertical");//获取z轴方向,Input.GetAxis("Vertical")代表Z轴方向移动 } private void FixedUpdate() { m_Movement.Set(horizontal, 0.0f, vertical);//设置该3D矢量的坐标,参数为用户输入的三维矢量 m_Movement.Normalize();//将该向量的长度设置为1 bool hasHorizontal = !Mathf.Approximately(horizontal, 0.0f);//判断是否有横向移动 bool hasVertical = !Mathf.Approximately(vertical, 0.0f);//判断是否有纵向移动;Mathf.Approximately用于比较两个浮点值,如果它们相似,则返回 true bool isWalking = hasHorizontal || hasVertical;//横向或者纵向有一个移动,玩家角色便是处于移动状态 m_Animator.SetBool("IsWalking", isWalking);//将变量传递给动画管理器 Vector3 desiredForward = Vector3.RotateTowards(transform.forward, m_Movement, turnSpeed * Time.deltaTime, 0f);//用三维矢量表示转向后的玩家角色朝向; m_Rotation = Quaternion.LookRotation(desiredForward);//设置四元数对象的值 if (isWalking)//如果走动,播放脚步音效,否则停止播放 { if (!m_AudioSource.isPlaying) { m_AudioSource.Play(); } }else { m_AudioSource.Stop(); } } private void OnAnimatorMove()//当动画播放引发根移动时执行 { m_Rigidbody.MovePosition(m_Rigidbody.position + m_Movement * m_Animator.deltaPosition.magnitude);//使用从用户输入获取到的三维矢量作为移动方向,使用动画中每次0.02秒移动的距离作为距离来移动 m_Rigidbody.MoveRotation(m_Rotation);//旋转该游戏对象 } }
using System.Collections; using System.Collections.Generic; using UnityEngine; ///41.键盘控制物体外观颜色代码/// /// public class Observer : MonoBehaviour//用来通过触发器代表敌人的视线监事玩家的代码 { public Transform player;//玩家的变换组件对象 public GameEnding gamEnding;//设置一个开关,boo变量,表示玩家是否被视线扫到 bool m_IsPlayerInRange;//声明游戏结束脚本组件类对象,为了调用游戏结束脚本中的共有方法 void OnTriggerEnter(Collider other)//禁入触发器事件 { if (other.transform == player)//如果进入触发区域的是玩家 { m_IsPlayerInRange = true;//开关变量设置为真 } } void OnTriggerExit(Collider other)//离开触发器事件 { if (other.transform == player)//当触发器区域中的是玩家 { m_IsPlayerInRange = false;//开关变量设置为假 } } void Update()//在Update中监控开关的值,一旦玩家进入视线触发器区域,执行对应的逻辑 { if (m_IsPlayerInRange)//触发器已经被触发 { Vector3 direction = player.position - transform.position + Vector3.up;//设置投射射线用到的方向矢量 Ray ray = new Ray(transform.position, direction);//创建射线 RaycastHit raycastHit;//射线击中对象,包括射线碰撞信息 if (Physics.Raycast(ray, out raycastHit))//使用物理系统发射射线,如果碰到物体进入第一层if。out代表第二个参数是输出参数,可以带出数据到参数中 { if (raycastHit.collider.transform == player)//如果碰到的是玩家 { gamEnding.CaughtPlayer();//调用GameEnding脚本中抓到玩家的方法 } } } } }
void Update()
{
if (Input.GetKeyDown(KeyCode.R))//按下R键
{
GetComponent().material.color = Color.red;//物体变为红色
}else if (Input.GetKeyDown(KeyCode.G))//按下G键
{
GetComponent ().material.color = Color.green;//物体变为绿色
}
else if (Input.GetKeyDown(KeyCode.B))//按下B键
{
GetComponent().material.color = Color.black;//物体变为黑色
}
}
42.gameObject.SetActive(false);用于激活游戏对象
43.transform.Translate表示将物体移动;transform.Rotate表示将物体旋转
44.transform.LookAt函数使一个游戏对象的变换组件面向另一个游戏对象的变换组件
45.Destroy() 函数删除游戏对象和组件
46. Instantiate() 函数用于创建预制件的克隆体。
47.Invoke()函数可用于延时调用方法(或某个函数)
48.Quaternion 四元数来管理游戏对象的旋转


