Unity实战——简易炉火
这一次感受了unity的粒子系统,并设计了一个简单的炉火,通过代码控制不同情况下炉火的外形。
最终效果
简易火炉
制作火焰
- 创建空对象,命名为 file,添加组件
Particle System
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-
- 修改
Emission
属性中的Rate over Time
,让系统在同一时间释放更多粒子
- 在
Shape
属性中修改形状为Box
,修改x方向的Rotation
为 -90,使粒子向上飘
- 为了让粒子系统更有火焰的形状,勾选
Size over LifeTime
属性,编辑波形,使其更接近火焰的形状
- 为了让颜色更接近火焰,勾选
Color over LifeTime
,调整颜色
- 调整基本的参数,让视觉效果更好
- 将
Fire
拖到Assets
中作为预制
脚本编写
从两个方面区分小火、中火和大火
- 火苗数量
- 火苗大小、形状
根据上述标准编写脚本调整火焰
本次脚本的结构较简单,是经典的mvc结构的简化
FirstController.cs
:程序的主控制器,负责加载资源、控制和回收火焰
以下对脚本中的方法进行介绍
Start
: 加载资源,对数据初始化
void Start()
{
fireList = new List<GameObject>();
userGUI = gameObject.AddComponent<UserGUI>();
status = userGUI.GetStatus();
}
Update
: 监听 status
属性,并调用响应函数控制火焰的变化
void Update()
{
int oldStatus = status;
status = userGUI.GetStatus();
if(oldStatus != status){
if(oldStatus > 0 && status == 0){
OffFire();
}
else{
if(status == 1){
SmallFire();
}
if(status == 2){
MiddleFire();
}
if(status == 3){
LargeFire();
}
}
}
}
SmallFire
, MiddleFire
, LargeFire
: 加载并调整粒子系统的属性
小火一共加载5个火苗,中火7个,大火9个。对应的scale,rateOverTime,startLifetime也通过代码修改,作为区分
public void SmallFire(){
DestroyFire();
for(int i = 0; i < 5; i++){
fire = Instantiate(Resources.Load("Prefabs/Fire"),
new Vector3(small_pos[i], 0f, z),
Quaternion.identity)
as GameObject;
fireList.Add(fire);
ParticleSystem ps = fire.GetComponent<ParticleSystem>();
var sh = ps.shape;
sh.radius = 0.69f;
sh.scale = new Vector3(0.1f, 0.1f, 0);
var em = ps.emission;
em.rateOverTime = 300f;
}
}
public void MiddleFire(){
DestroyFire();
for(int i = 0; i < 7; i++){
fire = Instantiate(Resources.Load("Prefabs/Fire"),
new Vector3(middle_pos[i], 0f, z),
Quaternion.identity)
as GameObject;
fireList.Add(fire);
ParticleSystem ps = fire.GetComponent<ParticleSystem>();
var sh = ps.shape;
sh.radius = 0.69f;
sh.scale = new Vector3(0.5f, 0.5f, 0);
var em = ps.emission;
em.rateOverTime = 500f;
}
}
public void LargeFire(){
DestroyFire();
for(int i = 0; i < 9; i++){
fire = Instantiate(Resources.Load("Prefabs/Fire"),
new Vector3(large_pos[i], 0f, z),
Quaternion.identity)
as GameObject;
fireList.Add(fire);
ParticleSystem ps = fire.GetComponent<ParticleSystem>();
var sh = ps.shape;
sh.radius = 0.69f;
sh.scale = new Vector3(1f, 1f, 0);
var em = ps.emission;
em.rateOverTime = 700f;
var main = ps.main;
main.startLifetime = 1.8f;
}
}
OffFire
: 熄灭火苗,方法是将粒子系统的loop属性改为False
public void OffFire(){
foreach(GameObject fire in fireList){
ParticleSystem ps = fire.GetComponent<ParticleSystem>();
var main = ps.main;
main.loop = false;
}
}
DestroyFire
: 销毁列表中的火苗
public void DestroyFire(){
foreach(GameObject fire in fireList){
fire.SetActive(false);
}
fireList.Clear();
}
UserGUI.cs
: 用户的主界面
public class UserGUI : MonoBehaviour
{
private FirstController firstController;
GUIStyle textStyle;
GUIStyle topicStyle;
int status;
// Start is called before the first frame update
void Start()
{
SetStyle();
status = 0;
}
// Update is called once per frame
void Update()
{
float x = Input.GetAxis("Horizontal");
float z = Input.GetAxis("Vertical");
}
void SetStyle(){
textStyle = new GUIStyle();
textStyle.normal.textColor = Color.black;
textStyle.fontSize = 30;
topicStyle = new GUIStyle();
topicStyle.normal.textColor = Color.black;
topicStyle.fontSize = 60;
}
void OnGUI(){
if (GUI.Button(new Rect(Screen.width/2 - 300, Screen.width/2 - 300, 60, 50), "熄灭"))
{
status = 0;
}
if (GUI.Button(new Rect(Screen.width/2 - 300, Screen.width/2 - 240, 60, 50), "小火"))
{
status = 1;
}
if (GUI.Button(new Rect(Screen.width/2 - 300, Screen.width/2 - 180, 60, 50), "中火"))
{
status = 2;
}
if (GUI.Button(new Rect(Screen.width/2 - 300, Screen.width/2 - 120, 60, 50), "大火"))
{
status = 3;
}
}
public int GetStatus(){
return status;
}
}