在C#中提供的很好的类型转换方式总结为:
Object => 已知引用类型——使用as操作符完成;
Object => 已知值类型——先使用is操作符来进行判断,再用类型强转换方式进行转换;
已知引用类型之间转换——首先需要相应类型提供转换函数,再用类型强转换方式进行转换;
已知值类型之间转换——最好使用系统提供的Conver类所涉及的静态方法。
在调用Instantiate()方法使用prefab创建对象时,接收Instantiate()方法返回值的变量类型必须和声明prefab变量的类型一致,否则接收变量的值会为null.
比如说,我在脚本里面定义:
public GameObject myPrefab;
那么在使用这个myPrefab做Instantiate()的时候,接收返回值变量的类型也必须是GameObject,如下:
GameObject newObject = Instantiate(myPrefab) as GameObject;
注意Instantiate()后面的as也要是GameObject。
又比如我们的prefab类型是我们自定义的UserObject
public UserObject prefab;
那么在使用Instantiate()时我们需要写成:
UserObject newObject = Instantiate(myPrefab) as UserObject;
比较容易犯的一个错误是我们声明的类型是:
public GameObject myPrefab;
在Instantiate()返回值却想要用Transform,如下:
Transform newObject = Instantiate(myPrefab) as Transform;
这个时候就会出现newObject为null的问题。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TankAttack : MonoBehaviour
{
public GameObject shellPrefab; //子弹预制体
public KeyCode fireKey = KeyCode.Space; //发射键,默认空格space键
private Transform firePosition; //子弹发射位置
public float shellSpeed = 15f; //子弹速度
// Start is called before the first frame update
void Start()
{
firePosition = transform.Find("FirePosition");
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(fireKey))
{
//GameObject.Instantiate为实例化元素,3个参数分别为 要实例化的预制体,实例化的位置,实例化的方向
GameObject go = GameObject.Instantiate(shellPrefab, firePosition.position, firePosition.rotation) as GameObject; //用GameObject类型接收,所以用as进行类型转换
//子弹的飞行速度和方向
go.GetComponent<Rigidbody>().velocity = go.transform.forward * shellSpeed;
}
}
}
OnTriggerEnter()与OnTriggerStay()
1.触发条件
- 双方必须有一方设置Is Trigger为Enable。
- 双方必须有一方设置有Rigidbody刚体组件。
2.代码调试
private void OnTriggerEnter(Collider other)
{
Debug.Log(message:other.name);//获取gameobject的名字
other.transform.position+= new Vector3(0, 0.44f, 0);//gameobject的y坐标发生变化。
}
3.触发分主动与被动
OnTriggerEnter(Collider other)与OntriggerStay(Collider other)的形参为被动的gameobject。
假设:ObjectA为设置为Is Trigger的一方,
ObjectB为接触的另一方。
情况1:当ObjectA主动接触ObjectB,形参other为ObjectB.
情况2:当ObjectB主动接触ObjectA,形参other为ObjectA。
Play On Awake:实例化后自动播放
子弹碰撞检测
创建Shell脚本,用于炮弹的碰撞事件
脚本挂载在Shell预制体上
Shell预制体的 Capsule Collider 属性的 Is Trigger 设置为开启状态,这样会与其它网格发生碰撞(碰撞后如不发生事件则直接穿透)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Shell : MonoBehaviour
{
public GameObject ShellExplosionPrefab; //子弹爆炸效果的预制体
// 脚本写完后,把做好的ShellExplosion预制体,挂在Shell预制体Shell脚本的ShellExplosionPrefab中
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
// 子弹发生碰撞时效果
private void OnTriggerEnter(Collider other)
{
// 实例化爆炸效果,当前位置,当前方向
GameObject.Instantiate(ShellExplosionPrefab, transform.position, transform.rotation);
// 把自身销毁
GameObject.Destroy(this.gameObject);
}
}
爆炸效果完成后删除
创建脚本DestroyForTime,挂在预制体ShellExplosion上
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DestroyForTime : MonoBehaviour
{
public float time = 1.5f; // 生存时间(设置动画时长)
// Start is called before the first frame update
void Start()
{
Destroy(this.gameObject, time); //预制体被实例化后,在time时间长度后销毁自身
}
// Update is called once per frame
void Update()
{
}
}
控制炮弹对坦克的伤害
先新增一个Tag:Tank,然后给Tank对象添加Tag属性为Tank,这样当炸弹碰撞的物体Tag属性是Tank时就是遇坦克发生碰撞,然后修改相关的属性等
Shell脚本修改为:
public class Shell : MonoBehaviour
{
public GameObject ShellExplosionPrefab; //子弹爆炸效果的预制体
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
// 子弹发生碰撞时效果
private void OnTriggerEnter(Collider other)
{
// 实例化爆炸效果,当前位置,当前方向
GameObject.Instantiate(ShellExplosionPrefab, transform.position, transform.rotation);
// 把自身销毁
GameObject.Destroy(this.gameObject);
// 子弹碰撞的物体tag为Tank,说明是坦克
if (other.gameObject.CompareTag("Tank"))
{
other.gameObject.SendMessage("TankDamage"); // 调用碰撞到的对象的TankDamage()方法
}
}
}
新增一个TankHealth脚本,为坦克血量,挂载在坦克预制体上,所有坦克都是相同的血量属性
public class TankHealth : MonoBehaviour
{
public int hp = 100; //坦克血量
public GameObject tankExplosion; //坦克阵亡效果
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
// 坦克受到伤害
void TankDamage()
{
if (hp <= 0) return; // 已阵亡
hp -= Random.Range(5, 15); //每次受到伤害损失5~15一个随机的伤害
if (hp <= 0)
{
// 受到伤害后阵亡,播放坦克阵亡动画 TankExplosion
// TankExplosion 的 Play On Awake 勾选上,被实例化后自动播放
GameObject.Instantiate(tankExplosion, transform.position + Vector3.up, transform.rotation); // 为了效果,爆炸动画向上移动1米 + Vector3.up
GameObject.Destroy(this.gameObject); // 销毁掉坦克自身
}
}
}