跳至主要内容

[外文翻译] 在unity3d上建立运行重新着色和衰退的粒子系统

粒子系统是极好的系统,适应于各种各样的特效在游戏中,包括火焰,爆炸,烟雾,水,灯光,行星模拟,还有很多,unity伴随着一个建立在粒子系统上的library可以用来实施这些特效在你的或者3d游戏上,而且在unity上实施这个粒子系统有着额外的灵活性和允许你创造更神奇的特效,有时候你有些情况需要要求一些专用化,这些是不可以被建立的。此外,最近我尝试实现实现一个粒子效果让粒子分散开来像爆炸一样,然后停留在一个地方,最后缓慢的淡出不断循环。当粒子不断发散随着它们的生命周期可以熟练的用过build-in editor,等待它们的是终止。
这里可以看到一个粒子系统是我创建的,它使用build-in particle editor unity中:
 
 
暂停粒子系统
根据你们所看到的,它开始于一个随机放射方向的粒子系统,然后停止,,这个暂停特效比直着向前扩展要好,而且可以实现通过贴上一个代码在粒子系统中让它暂停然后继续
 
public class ParticleScript : MonoBehaviour {

    public float timeToPause = 2.0f;
   
    private ParticleSystem system;
    private float time;
   
    void Awake() {
        system = GetComponent();
    }
   
    void Update() {
        time += Time.deltaTime;
       
        if (!system.isPaused && time > timeToPause) {
            system.Pause();
        }
    }
}
我们开始通过定义一个public float 叫做timeToPause 表示多长时间这个粒子应该持续播放在暂停之前,在Update中,我们update timeTime.deltaTime和暂停这个粒子系统用pause()在粒子系统本身上
这些都很简单并且好用,但是我们仍然需要修改粒子的颜色在暂停的视乎,这个主意是一旦粒子系统被暂停,他就开始衰退直到它消失不可见。

重新着色粒子
我们将要做的是重新着色每一个单独的粒子,因为他们可能有同样的颜色取决于你的粒子系统怎样被配置。在这个粒子中,我们将会修改粒子的alpha在衰退的部分,但你可以应用同样的方法在任何合成的颜色中。
第一件事我们要做的是引用到当前的粒子在系统中当我们暂停的时候:
 
public class ParticleScript : MonoBehaviour {

    ...
    
    private ParticleSystem.Particle[] particles;
    
    ...
    
    void Update() {
        time += Time.deltaTime;
        
        if (!system.isPaused && time > timeToPause) {
            system.Pause();
            
            particles = new ParticleSystem.Particle[system.particleCount];
            system.GetParticles(particles);
        }
    }
}
我们定义一个队列中的粒子项目我们将会用使用储存粒子当我们暂停了系统。我们然后初始化它与当前数量的粒子在系统中用system.particleCount来作用到一个缓冲区,然后前往有粒子储存的缓冲区队列中用system.GetParticles
现在我们可以反复处理和修改这些粒子根据这个队列。在Update中,我们将要添加一些逻辑当系统被暂停来重新着色粒子像这样:
public class ParticleScript : MonoBehaviour {

    ...
    
    public float lifespan = 5.0f;
    
    ...
    
    
    void Update() {
        ...
        
        if (particles != null) {
            for (int p = 0; p < particles.Length; p++) {
                Color color = particles[p].startColor;
                color.a = ((lifespan - time + timeToPause) / lifespan);
                
                particles[p].startColor = color;
            }
            
            system.SetParticles(particles, particles.Length);
        }
    }
}
我们开始通过确定这个系统已经被暂停而且粒子已经被初始化,然后合并这些已经储藏的粒子当我们暂停这个系统的时候。对于单个粒子,我们抓住他们当前的颜色,并且更新alpha作为百分比的时间针对已经确认与总时间线对比过得粒子。同样需要注意的我们忽略了 timeToPause 添加到时间线来确认如何“淡出”之前的粒子

随着时间的推移这些粒子将会顺滑的淡出像这样:
 

表现
根 据这些粒子系统的数量,当你的粒子消散时,在每一个系统中的粒子,上面有一些规则有着基本的实施需要被标记,例如,你可能不想更新每一帧的粒子,而只更新 了第五帧,例如,你可能缓存当前的颜色,只更新粒子当这些变化非常重要时,列如,不要更新所有的粒子,在粒子系统中,当不同的alpha的差异是非常小的,甚至不会很明显。
如果你还想摧毁粒子系统,当它完全淡出识图(color.a <= 0f)而不是只是让它围绕。
这些表现的提升你选择的,如果有的话,将取决于你的案例,但是还是希望能给你一些启发对于一些特效你想要实现在你的游戏当中
完整的代码
最后,这里是完整的脚本,如下:
using UnityEngine;
using System.Collections;

public class ParticleScript : MonoBehaviour {
    
    public float lifespan = 5.0f;
    public float timeToPause = 2.0f;
    
    private ParticleSystem.Particle[] particles;
    private ParticleSystem system;
    private float time;
    
    void Awake() {
        system = GetComponent();
    }
    
    
    void Update() {
        time += Time.deltaTime;
        
        if (!system.isPaused && time > timeToPause) {
            system.Pause();
        
            particles = new ParticleSystem.Particle[system.particleCount];
            system.GetParticles(particles);
        }
        
        if (particles != null) {
            for (int p = 0; p < particles.Length; p++) {
                Color color = particles[p].startColor;
                color.a = ((lifespan - time + timeToPause) / lifespan);
                
                particles[p].startColor = color;
            }
        
            system.SetParticles(particles, particles.Length);
        }
    }
}
 
 
 
 

评论

此博客中的热门博文

Unity3D研究院之提取游戏资源的三个工具支持Unity5(八十四)

这两天无意间又发现了两个提取Unity游戏资源的工具,这会儿刚好有时间我就码点字总结一下。 一、disunity 因为之前写过了所以这里就不介绍了 。Unity3D研究院之mac上从.ipa中提取unity3D游戏资源(六十六)  http://www.xuanyusong.com/archives/2584 二、UnityAssetsExplorer 下载地址: http://www.nexusmods.com/pillarsofeternity/mods/27/?tab=2&navtag=http%3A%2F%2Fwww.nexusmods.com%2Fpillarsofeternity%2Fajax%2Fmodfiles%2F%3Fid%3D27&pUp=1 百度云下载地址: http://pan.baidu.com/s/1AwTrg 如果你想解Unity5的游戏包,请使用 UnityAssetsExplorer 1.5 以上版本。 百度云下载地址: http://pan.baidu.com/s/1sjkjSJz 如下图所示,OpenAssets-File 选一个 .asset 或者一个.assetbundle 然后Extract All即可导出,感觉只是在disunity上增加了一个可视化的功能。 三、UnityStudio 其实我觉得这个工具非常牛逼、前面两个都只能把资源解开,预览图片资源得用别的工具才能打开。然而UnityStudio可以直接在自己的软件上查 看图片、shader、文本、还能直接播放音频、甚至还能看场景Hierarchy视图的树状结构。强烈推荐用UnityStudio啊。 下载地址: http://forum.xentax.com/viewtopic.php?f=10&t=11807 百度云下载地址: http://pan.baidu.com/s/1hqjMnOg UnityStudio最新版本下载 支持unity5.x   https://github.com/Perfare/UnityStudio/releases 直接预览图片 直接播放音频 查看场景树状结构 查看Shader代码。 ...

[3D跑酷] GUIManager UI管理

UI元素更新及界面跳转 继上篇日志《Unity开发之 GUIClickEventReceiver》,再谈一下我们如何管理游戏中的UI元素更新及界面跳转 UI绑定 图一:Inspector面板 Public GameObjectName与GameObject一一对应 UI结构及命名规范 图二:Hierarchy面板 UI父子结构及组件命名规范 UI枚举种类 图三:enum GUIState UI绑定代码 图四:public UI控件定义 与Hierarchy命名规范 UI主要方法及逻辑 图五:主要方法及逻辑 主要方法 1、隐藏Transform及子Transform #if !UNITY_3_5 private void activeRecursively(Transform obj, bool active) { foreach (Transform child in obj) { activeRecursively(child, active); } obj.gameObject.SetActive(active); } #endif private GameObject panelFromState(GUIState state) { switch (state) { case GUIState.MainMenu: return mainMenuPanel; case GUIState.InGame: return inGamePanel; case GUIState.EndGame: return endGamePanel; case GUIState.Store: return storePanel; case GUIState.Stats: return statsPanel; case GUISt...

[3D跑酷] AudioManager

Unity音频管理 游戏中的声音管理最常用的组件莫过于AudioSource和AudioClip,我的做法是建立是一个AudioManager类(单例类)管理各个音频,谈一下我的经验: 函数列表 Start函数:设置音频整体参数; 编辑器面板 拖拽文件赋值 AudioSource文档 逻辑实现代码 public void playSoundEffect(SoundEffects soundEffect) { AudioClip clip = null ; float pitch = 1; switch (soundEffect) { case SoundEffects.ObstacleCollisionSoundEffect: clip = obstacleCollision; break ; case SoundEffects.CoinSoundEffect: clip = coinCollection; pitch = 1.5f; break ; case SoundEffects.PowerUpSoundEffect: clip = powerUpCollection; break ; case SoundEffects.GameOverSoundEffect: clip = gameOver; break ; case SoundEffects.GUITapSoundEffect: clip = guiTap; break ; } soundEffectsAudio.pitch = pitch; //音调 so...