Unistorm是Unity中的一个天气系统,它功能强大,效果优美。本文所述UniStorm为3.0版本,仅用于学习之用。
一、如何设置【白天】、【黑夜】和【天气类型】?
在Running模式下,按下Esc按键,会【弹出】或者【隐藏】天气设置界面
- 第一个滑动条为:当下的时辰【对应从早到晚的进度】
- 第二个下拉框为:天气的类型
- 第三个按钮:确定按钮
二、如何禁用时间流淌(Time Flow)功能?
有时候,用户操作的慢了,天气突然从白天变成黑夜,乌漆嘛黑的伸手不见五指。为了防止这种尴尬,所以有时候需要关闭时间流淌的功能。
【UniStorm System】->【Time】->【Time Flow】 设置成[Disabled]
三、模拟飞机在云团中穿行时,如何制作一个全景包围球?
需求:UniStorm中的天空盒是一个半球,如果要模拟飞机在云团中穿行,那么需要一整个球把飞机包住。
解决:在运行状态下,再复制出一个天气半球,并设置两个半球是合在一起的。
(1)云层的天空半球
/// <summary>/// 云层组件/// </summary>[Header("云层组件")]publicGameObject UniStormClouds;
(2)复制天空半球,设置对原来的球的对面,让两个半球合拢成一个球。
参数为硬编码,提前在Editor的running模式下,手工操作一遍,然后保存这些参数。
privatevoidCreateUniStormClouds(){var uniStormCloudsClone = GameObject.Instantiate(UniStormClouds);
uniStormCloudsClone.transform.parent = UniStormClouds.transform.parent;
uniStormCloudsClone.transform.localPosition =newVector3(-0.06383133f,-293f,-223f);
uniStormCloudsClone.transform.rotation = Quaternion.Euler(90,0,0);
uniStormCloudsClone.transform.localScale =newVector3(1000000,1000001,700000);}
四、如何关闭鼠标控制相机转动的功能
相机上挂在了一个脚本【Pause】,把这个脚本禁用即可。
天气系统自带的【相机旋转功能】可能会与【祖传的角色控制功能】冲突,所以需要禁用。
五、按【Esc】键的时候,天气设置界面不再显示和隐藏,如何实现?
场景初始化之后,会自动生成一个叫【UniStorm Canvas】的UI界面。
(1)简单粗暴的解决方法:在启动的时候,抓取这个对象,然后把他们隐藏掉。
//等待几秒初始化后,找到UniStorm Canvas组件,然后隐藏var UniStormCanvas = GameObject.FindObjectsOfType<Canvas>(true).First(x => x.name =="UniStorm Canvas");
UniStormCanvas.gameObject.SetActive(false);
(2)最优的实现:插件已经提供这个功能的【启用】和【禁用】参数了
(3)正常的操作就是先找到UI,然后在关闭该选项
/// <summary>/// 获取设置天气的三个UI元素/// 时辰-slider/// 天气类型-dropdownList/// 确定更改-button/// </summary>/// <param name="ctk"></param>/// <returns></returns>privateasyncUniTaskGetUiElements(CancellationToken ctk){//【1】等待一段时间进行初始化await UniTask.DelayFrame(2,cancellationToken:ctk);//【2】获取用来设置天气的3个UI组件var UniStormCanvas = GameObject.FindObjectsOfType<Canvas>(true).First(x => x.name =="UniStorm Canvas");
TimeSlider = UniStormCanvas.GetComponentsInChildren<Slider>(true).Where(x => x.name =="Time Slider").First();
WeatherDropdown = UniStormCanvas.GetComponentsInChildren<Dropdown>(true).Where(x => x.name =="Weather Dropdown").First();
ChangeWeatherBtn = UniStormCanvas.GetComponentsInChildren<Button>(true).Where(x => x.name =="Change Weather Button").First();//【3】关闭设置菜单
unistorm.UseUniStormMenu = UniStormSystem.EnableFeature.Disabled;}
六、如何通过代码更换天气
在不破坏UniStorm工程文件的前提下,思路:
1、在运行时获取设置天气的UI元素,
2、赋值【时辰】和【天气类型】,激发【确定】按钮的click事件。
#if UNITY_EDITOR[ContextMenu("天气设置")]#endifasyncUniTasktest4(){Setweather();}privateasyncUniTaskSetweather(){await UniTask.Delay(TimeSpan.FromSeconds(2f));//找到组件var UniStormCanvas = GameObject.FindObjectsOfType<Canvas>(true).First(x => x.name =="UniStorm Canvas");
Debug.Log(UniStormCanvas);
TimeSlider = UniStormCanvas.GetComponentsInChildren<Slider>(true).Where(x => x.name =="Time Slider").First();
WeatherDropdown = UniStormCanvas.GetComponentsInChildren<Dropdown>(true).Where(x => x.name =="Weather Dropdown").First();
ChangeWeatherBtn = UniStormCanvas.GetComponentsInChildren<Button>(true).Where(x => x.name =="Change Weather Button").First();//设置value
TimeSlider.value=0.5f;
WeatherDropdown.SetOption("Thunderstorm");
ChangeWeatherBtn.onClick.Invoke();}
七、UniStorm的主要入口脚本
【UniStorm System】物体上有一个叫UniStormSystem的主脚本
【UniStorm Demo Player】物体和它的子物体下面有一些相机对应的功能
如果要读源码应该从UniStormSystem.cs下手
八、附录——天气控制的脚本
(1)获取天空半球,获取设置天气的UI元素,简单设置天气
namespaceAsyncStep{/// <summary>/// 获取天气设置的组件/// </summary>publicclassSetWeatherV3:MonoBehaviour{/// <summary>/// 云层组件/// </summary>[Header("云层组件")]publicGameObject UniStormClouds;/// <summary>/// 效果相机/// </summary>[Header("效果相机")]publicCamera effectCamera;/// <summary>/// 地形/// </summary>[Header("地形")]publicTerrain MyTerrain;/// <summary>/// 天气系统主脚本/// </summary>[Header("天气系统主脚本")]publicUniStormSystem unistorm;/// <summary>/// 天气类型/// </summary>[Header("天气类型-测试用")]publicstring weatherType ="Thunderstorm";/// <summary>/// 时间设置/// </summary>[Header("======运行时自动获取UI组件======")][Header("时间设置")]publicSlider TimeSlider;/// <summary>/// 天气种类/// </summary>[Header("天气种类")]publicDropdown WeatherDropdown;/// <summary>/// 确认按钮/// </summary>[Header("确认按钮")]publicButton ChangeWeatherBtn;voidStart(){GetUiElements(this.GetCancellationTokenOnDestroy());}/// <summary>/// 获取设置天气的三个UI元素/// 时辰-slider/// 天气类型-dropdownList/// 确定更改-button/// </summary>/// <param name="ctk"></param>/// <returns></returns>privateasyncUniTaskGetUiElements(CancellationToken ctk){//【1】等待一段时间进行初始化await UniTask.DelayFrame(2,cancellationToken:ctk);//【2】获取用来设置天气的3个UI组件var UniStormCanvas = GameObject.FindObjectsOfType<Canvas>(true).First(x => x.name =="UniStorm Canvas");
TimeSlider = UniStormCanvas.GetComponentsInChildren<Slider>(true).Where(x => x.name =="Time Slider").First();
WeatherDropdown = UniStormCanvas.GetComponentsInChildren<Dropdown>(true).Where(x => x.name =="Weather Dropdown").First();
ChangeWeatherBtn = UniStormCanvas.GetComponentsInChildren<Button>(true).Where(x => x.name =="Change Weather Button").First();//【3】关闭设置菜单
unistorm.UseUniStormMenu = UniStormSystem.EnableFeature.Disabled;}#if UNITY_EDITOR[ContextMenu("天气设置")]#endifasyncUniTasktest4(){Setweather();}privateasyncUniTaskSetweather(){//设置value
TimeSlider.value=0.5f;
WeatherDropdown.SetOption(weatherType);
ChangeWeatherBtn.onClick.Invoke();}}}
(2)设置天气类型
usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingSystem.Threading;usingCysharp.Threading.Tasks;usingUnityEngine;usingstatictxlib;namespaceAsyncStep{/// <summary>/// 天气控制:天气类型 + 日期时刻/// </summary>publicclassSetWeatherInfoControl:MonoBehaviour,IFlowAsync{/// <summary>/// 天气组件/// </summary>[Header("天气组件")]publicSetWeatherV3 weather;/// <summary>/// 时间点/// </summary>[Header("时间点")]publicfloat sliderValue;/// <summary>/// 天气类型/// </summary>[Header("天气类型")]publicstring weatherType;/// <summary>/// 本步骤的名字:Start中预先缓存,防止报空/// </summary>publicstring this_name;// Start is called before the first frame updatevoidStart(){
this_name =this.name;}#if UNITY_EDITOR[ContextMenu("测试")]#endifvoidTest(){FlowAsync(this.GetCancellationTokenOnDestroy());}publicasyncUniTaskFlowAsync(CancellationToken ctk){try{
weather.TimeSlider.value= sliderValue;
Debug.Log(weather.TimeSlider.value);//设置value
weather.TimeSlider.value= sliderValue;
weather.WeatherDropdown.SetOption(weatherType);
weather.ChangeWeatherBtn.onClick.Invoke();}catch(Exception e){
Debug.Log($"{this_name}报错:{e.Message}");
Debug.Log($"\n 抛出一个OperationCanceledException");thrownewOperationCanceledException();}
Debug.Log($"{this.name} 执行完毕");}}}
版权归原作者 dzj2021 所有, 如有侵权,请联系我们删除。