子弹的轨迹是由2D坐标屏幕的camera位置射向3D坐标世界的某个点。
Unity中的协程不是异步的,yield之后退出,下一帧再接着执行。执行时机是在update()和lateUpdate()之间。适合用场合:如等待几秒后销毁,文件加载好后处理。
发射子弹并击中目标的代码:
void Start() {
_camera = GetComponent<Camera>();
// 鼠标锁定且隐藏,按ESC解除锁定
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
// 在每一帧完成3D场景渲染后调用
void OnGUI() {
int size = 12;
float posX = _camera.pixelWidth/2 - size/4;
float posY = _camera.pixelHeight/2 - size/2;
// 这里用基础GUI构造了一个TextLabel
GUI.Label(new Rect(posX, posY, size, size), "*");
}
void Update() {
if (Input.GetMouseButtonDown(0)) {
// 从camera中心发出
Vector3 point = new Vector3(_camera.pixelWidth/2, _camera.pixelHeight/2, 0);
// 这个方法垂直屏幕发出射线
Ray ray = _camera.ScreenPointToRay(point);
RaycastHit hit;
if (Physics.Raycast(ray, out hit)) {
// 击中的对象
GameObject hitObject = hit.transform.gameObject;
ReactiveTarget target = hitObject.GetComponent<ReactiveTarget>();
// 若找到相应脚本,则认为是敌人,否则是普通物体
if (target != null) {
target.ReactToHit();
} else {
StartCoroutine(SphereIndicator(hit.point));
}
}
}
}
// 调用协程方法
private IEnumerator SphereIndicator(Vector3 pos) {
GameObject sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
sphere.transform.position = pos;
// 暂停1秒再销毁
yield return new WaitForSeconds(1);
Destroy(sphere);
}
tweens可以让敌人被击中后倾斜的动作更加顺滑。
敌人AI代码:
void Start() {
_alive = true;
}
void Update() {
if (_alive) {
// 1. 向前移动(rotate()和translate()都默认使用本地坐标系)
transform.Translate(0, 0, speed * Time.deltaTime);
Ray ray = new Ray(transform.position, transform.forward);
RaycastHit hit;
if (Physics.SphereCast(ray, 0.75f, out hit)) {
GameObject hitObject = hit.transform.gameObject;
// 2. 若发射线击中物体了
if (hitObject.GetComponent<PlayerCharacter>()) {
// 若没有火球则产生火球
if (_fireball == null) {
_fireball = Instantiate(fireballPrefab) as GameObject;
_fireball.transform.position = transform.TransformPoint(Vector3.forward * 1.5f);
_fireball.transform.rotation = transform.rotation;
}
}
// 3. 若在一定范围内
else if (hit.distance < obstacleRange) {
// 4. 则旋转随机角度
float angle = Random.Range(-110, 110);
transform.Rotate(0, angle, 0);
}
}
}
}
prefab是可被不同场景重复使用的GameObject,它可以看做是一种asset,在场景中需要使用时动态加载,这时产生的一个copy叫做instance。关键词:动态加载,重复使用。
敌人死亡后重生的做法是:创建一个空GameObject,下面挂载一个脚本SceneController,每帧判断下当前场景中是否有enemy prefab的instance,没有则创建。
火球运动的代码:
void Update() {
transform.Translate(0, 0, speed * Time.deltaTime);
}
// 碰撞时触发(需要设置rigidBody)
void OnTriggerEnter(Collider other) {
PlayerCharacter player = other.GetComponent<PlayerCharacter>();
if (player != null) {
// 执行扣血代码
player.Hurt(damage);
}
Destroy(this.gameObject);
}
敌人和玩家子弹的处理不一样,一个是用prefab,可以看到移动过程;另一个是raycast,瞬间击中。
art asset的类型分类:material, texture, model, animation, particle system。
Unity支持的2D图形文件类型:PNG,JPG,GIF,BMP,TGA,TIFF,PICT,PSD。其中PNG是无损压缩,JPG和GIF是有损压缩。Unity中推荐使用的格式是:PNG,TGA和PSD。
将texture应用到model的方法:可以直接拖拽到model上,这时material会自动生成;也可以先创建material,再将texture和material关联。
Unity支持的3D模型格式有:FBX,Collada,OBJ,3DS,DXF,Maya,3ds Max,Blender。推荐的是FBX和Collada,它们同时支持mesh和animation。
粒子系统用于表现大量物体的运动(如火焰、烟雾、水)。