Unity 3D 游戏通用系统设置页面,自定义按键设置,背景虚化,图像设置,亮度对比度饱和度音量调节,分辨率窗口化,帧率垂直同步,抗锯齿,阴影质量,纹理质量设置
Posted 唐沢
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 3D 游戏通用系统设置页面,自定义按键设置,背景虚化,图像设置,亮度对比度饱和度音量调节,分辨率窗口化,帧率垂直同步,抗锯齿,阴影质量,纹理质量设置相关的知识,希望对你有一定的参考价值。
简易的游戏通用设置页面
本文章包含所有代码及UI结构
页面效果:
UI结构(便于管理):
代码:
思路:
整个页面的父物体SettingPanel上挂载管理代码,用于获取设置页面中所有的功能按钮,拖动条,下拉框等,做一个单例以便其他Panel获取.
有三个按钮有二级页面,所以还需要分别写三个Panel管理代码管理不同的页面,他们都有一个相同点,打开关闭(渐变)激活状态等,所以把这些功能写道一个代码里作为他们的父物体,
先抛开需求如何实现,这些数据必须是要保存的,不能打开游戏又需要重新设置一遍,需要创建一个数据保存类,其功能就是,保存数据(保存到本地),读取数据,默认数据等…,可以在关闭页面时统一保存到本地,打开游戏时读取并加载本地数据,加载数据与保存数据(保存到缓存)的功能应该是SettingPanel来完成,因为所有的按钮,拖动条,下拉框都在这个代码上,也便于赋值.
功能实现问题:
1.内容中的亮度,对比饱和这种是Shader效果,所以并不能通用与各种渲染管线,目前只考虑通用渲染管线,如果有自己的渲染管线,也很好修改.
2.在制作过程中Slider不能仅仅是拖动效果,还需要显示具体的数值并修改数值,所以每一个Slider后都需要一个输入框连接拖拽值.
3.分辨率窗口化帧率等这些可以调用系统设置来完成,抗锯齿,阴影,图像质量(根据项目设定,暂时用系统),按键输入就必须是自己写功能,是时候上代码了.
其中用到了几个小工具
文件工具
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace TFramework
public partial class FileUtil
/// <summary>
/// 错误内容
/// </summary>
static string Error = "错误!没有寻找到文件,建议查看文件名称是否输入错误?";
//暂时存储的文件内容
static List<string> datas = new List<string>();
/// <summary>
/// 在本地读取文件全部数据
/// </summary>
/// <param name="txtName">文件名</param>
/// <returns>返回每行</returns>
public static List<string> ReadLocalData(string txtName)
datas.Clear();
StreamReader sr = null;//读取
if (new FileInfo(Application.persistentDataPath + "\\\\" + txtName).Exists)
sr = File.OpenText(Application.persistentDataPath + "\\\\" + txtName);//读取文件
else
datas.Add(Error);
return datas;
//读取所有行
string data = null;
do
data = sr.ReadLine();
if (data != null)
datas.Add(data);
while (data != null);
sr.Close();//关闭流
sr.Dispose();//销毁流
return datas;
/// <summary>
/// 在本地写入一行数据
/// </summary>
/// <param name="txtName">文件名</param>
/// <param name="data">写入数据</param>
public static void WriteLocalTxt(string txtName, string data)
StreamWriter sw;//写入
FileInfo t = new FileInfo(Application.persistentDataPath + "\\\\" + txtName);//文件流
if (!t.Exists)
sw = t.CreateText();//创建
else
sw = t.AppendText();//打开文件
sw.WriteLine(data);//写入数据
sw.Flush();//清除缓冲区
sw.Close();//关闭流
sw.Dispose();//销毁流
/// <summary>
/// 删除本地文件
/// </summary>
/// <param name="txtName"></param>
public static void DeleteLocalTxt(string txtName)
FileInfo t = new FileInfo(Application.persistentDataPath + "\\\\" + txtName);//文件流
t.Delete();
/// <summary>
/// 清空StreamingAssetsData
/// </summary>
/// <param name="txtName"></param>
public static void ClearStreamingAssetsData(string txtName)
string Path = GetStreamingAssetsPath();
txtName = Path + txtName;
StreamWriter tmpWrite = new StreamWriter(txtName);
tmpWrite.WriteLine("");
tmpWrite.Close();
/// <summary>
/// 读取StreamingAssets目录文件
/// </summary>
/// <param name="path">路径:"/文件名加后缀"</param>
/// <returns>返回字符串</returns>
public static List<string> ReadStreamingAssetsData(string path)
FileInfo t = new FileInfo(GetStreamingAssetsPath() + "\\\\" + path);//文件流
if (!t.Exists)
return null;
string Path = GetStreamingAssetsPath();
path = Path + path;
//打开文件
StreamReader tmpReader = new StreamReader(path);
datas.Clear();
string ReadRow = tmpReader.ReadLine();
while (ReadRow != null)
datas.Add(ReadRow);
ReadRow = tmpReader.ReadLine();
tmpReader.Close();
return datas;
/// <summary>
/// StreamingAssets目录写入一行数据
/// </summary>
/// <param name="path"></param>
public static void WriteStreamingAssetsData(string path, string data)
ReadStreamingAssetsData(path);
//string Path = GetStreamingAssetsPath();
//path = Path + path;
//StreamWriter tmpWrite = new StreamWriter(path);
StreamWriter tmpWrite;
FileInfo t = new FileInfo(GetStreamingAssetsPath() + "\\\\" + path);//文件流
if (!t.Exists)
tmpWrite = t.CreateText();//创建
else
tmpWrite = t.AppendText();//打开文件
//foreach (string linedata in datas)
//
// tmpWrite.WriteLine(linedata);
//
tmpWrite.WriteLine(data);
tmpWrite.Close();
/// <summary>
/// 得到StreamingAssets目录
/// </summary>
/// <returns></returns>
static string GetStreamingAssetsPath()
string str = Application.streamingAssetsPath + "/";
return str;
字符串功能扩展
using System.Collections.Generic;
namespace TFramework
public partial class StringUtil
/// <summary>
/// 替换字符
/// </summary>
/// <param name="str">需要修改的字符串</param>
/// <param name="Target">需要替换的字符串</param>
/// <param name="ModifyTarget">替换为ModifyTarget</param>
/// <returns></returns>
public static string Replace(string str, string Target, string ModifyTarget)
string ModifyStr = "";
ModifyStr = System.Text.RegularExpressions.Regex.Replace(str, Target, ModifyTarget);
return ModifyStr;
/// <summary>
/// 替换字符
/// </summary>
/// <param name="str">需要修改的字符串</param>
/// <param name="Target1">需要替换的其中一个字符串</param>
/// <param name="Target2">需要替换的其中一个字符串</param>
/// <param name="ModifyTarget1">Target1替换为ModifyTarget1</param>
/// <param name="ModifyTarget2">Target2替换为ModifyTarget2</param>
/// <returns></returns>
public static string Replace(string str, string Target1, string Target2, string ModifyTarget1, string ModifyTarget2)
string ModifyStr = "";
ModifyStr = System.Text.RegularExpressions.Regex.Replace(str, Target1, ModifyTarget1);
return System.Text.RegularExpressions.Regex.Replace(ModifyStr, Target2, ModifyTarget2);
/// <summary>
/// 字符串截取(两个字符中间的字符串)
/// </summary>
/// <param name="str">需要截取的字符串</param>
/// <param name="LocationStart">从这个地方开始截取</param>
/// <param name="LocationEnd">截取到这个地方</param>
/// <returns></returns>
public static string Substring(string str, char LocationStart, char LocationEnd)
if (str.Length < 3)
return "字符串少于3,无法截取";
string ModifyStr = "";
int index0 = 0;
int index1 = 0;
for (int j = 0; j < str.Length; j++)
if (str[j] == LocationStart)
index0 = j;
if (str[j] == LocationEnd)
index1 = j;
ModifyStr = str.Substring(index0 + 1, index1 - index0 - 1);
return ModifyStr;
/// <summary>
/// 字符串截取(字符到开始或结束)
/// </summary>
/// <param name="str"></param>
/// <param name="TargetChar"></param>
/// <param name="IsAback"></param>
/// <returns></returns>
public static string Substring(string str, char TargetChar, bool IsAback)
if (str.Length < 3)
return "字符串少于3,无法截取";
string ModifyStr = "";
int index = 0;
for (int j = 0; j < str.Length; j++)
if (str[j] == TargetChar)
index = j;
if (IsAback)
ModifyStr = str.Substring(index + 1, str.Length - 1 - index);
else
ModifyStr = str.Substring(0, index);
return ModifyStr;
/// <summary>
/// 字符串截取
/// </summary>
/// <param name="str">需要截取的字符串</param>
/// <param name="LocationStart">从这个地方开始截取</param>
/// <param name="LocationEnd">截取到这个地方</param>
/// <returns></returns>
public static List<string> Substrings(string str, char LocationStart, char LocationEnd)
List<string> ModifyStrs = new List<string>();
if (str.Length < 3)
return null;
int index0 = 0;
int index1 = 0;
for (int j = 0; j < str.Length; j++)
if (str[j] == LocationStart)
index0 = j;
if (str[j] == LocationEnd)
index1 = j;
ModifyStrs.Add(str.Substring(index0 + 1, index1 - index0 - 1));
return ModifyStrs;
public static List<string> Substrings(string str, char LocationStart1, char LocationEnd1, char LocationStart2, char LocationEnd2)
List<string> ModifyStrs = new List<string>();
if (str.Length < 3)
return null;
int index0 = -1;
int index1 = -1;
int index2 = -1;
int index3 = -1;
for (int j = 0; j < str.Length; j++)
if (str[j] == LocationStart1)
index0 = j;
if (str[j] == LocationStart2)
index2 = j;
if (str[j] == LocationEnd1 && index0 != -1)
index1 = j;
ModifyStrs.Add(str.Substring(index0 + 1, index1 - index0 - 1));
if (str[j] == LocationEnd2 && index2 != -1)
index3 = j;
ModifyStrs.Add(str.Substring(index2 + 1, index3 - index2 - 1));
return ModifyStrs;
PanelBase(页面父类)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PanelBase : MonoBehaviour
CanvasGroup CanvasGroup_Panel;
bool ActivateChangeAlpha = false;
float AlphaValue = 0;
[HideInInspector]
public bool ActivateState=false;
protected virtual void Start()
CanvasGroup_Panel = GetComponent<CanvasGroup>();
public virtual void ShowPanel()
AlphaValue = 1;
ActivateChangeAlpha = true;
CanvasGroup_Panel.blocksRaycasts = true;
ActivateState = true;
public virtual void HidePanel()
AlphaValue = 0;
ActivateChangeAlpha = true;
CanvasGroup_Panel.blocksRaycasts = false ;
ActivateState = false;
protected virtual void Update()
if (ActivateChangeAlpha)
CanvasGroup_Panel.alpha = Mathf.Lerp(CanvasGroup_Panel.alpha, AlphaValue, 0.1f);
if (Mathf.Abs(CanvasGroup_Panel.alpha - AlphaValue) < .1f)
CanvasGroup_Panel.alpha = AlphaValue;
ActivateChangeAlpha = false;
DataProcessing(数据保存类)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TFramework;
public class DataProcessing : MonoBehaviour
public float Data_LuminanceValue=1, Data_ContrastValue=1, Data_SaturationValue=1, Data_AudioValue=1, Data_VisibilityValue=200;
public int Data_ResolutionIndex = 0, Data_FPSIndex = 1, Data_AntiAliasingIndex=0, Data_ShadowQualityIndex=2, Data_GrainQualityIndex=2;
public bool Data_IsWindow=false, Data_IsVsync=false;
public List<int> Keypads = new List<int>();
private void Awake()
ReadDate();
/// <summary>
/// 数据保存在本地StreamingAssets文件夹
/// </summary>
public void SaveDate()
FileUtil.ClearStreamingAssetsData("SettingData");//清空之前的数据
FileUtil.WriteStreamingAssetsData("SettingData", "Data_LuminanceValue=" + Data_LuminanceValue);
FileUtil.WriteStreamingAssetsData("SettingData", "Data_ContrastValue=" + Data_ContrastValue);
FileUtil.WriteStreamingAssetsData("SettingData", "Data_SaturationValue=" + Data_SaturationValue);
FileUtil.WriteStreamingAssetsData("SettingData", "Data_AudioValue=" + Data_AudioValue);
FileUtil.WriteStreamingAssetsData("SettingData", "Data_VisibilityValue=" + Data_VisibilityValue);
FileUtil.WriteStreamingAssetsData("SettingData", "");
FileUtil.WriteStreamingAssetsData("SettingData", "Data_ResolutionIndex=" + Data_ResolutionIndex);
FileUtil.WriteStreamingAssetsData("SettingData", "Data_FPSIndex=" + Data_FPSIndex);
FileUtil.WriteStreamingAssetsData("SettingData", "Data_AntiAliasingIndex=" + Data_AntiAliasingIndex);
FileUtil.WriteStreamingAssetsData("SettingData", "Data_ShadowQualityIndex=" + Data_ShadowQualityIndex);
FileUtil.WriteStreamingAssetsData("SettingData", "Data_GrainQualityIndex=" + Data_GrainQualityIndex);
FileUtil.WriteStreamingAssetsData("SettingData", "");
FileUtil.WriteStrea黑魂复刻游戏的按键长按功能——Unity随手记
今天实现的内容:
按键长按
长按是判断我们按下一个按键的持续时间是否大于一个固定值,持续时间大于该值说明当前我们正在长按,在黑魂游戏中,玩家的翻滚/后跳和冲刺都是一个按键,区别在于长按该键是冲刺,短按就是翻滚/后跳。我们依然会用到计时器来实现按钮长按。
在按下按键后,我们会开启delaying计时器,在delaying计时器执行期间按键的isDelaying信号会被设置为true。所以,按住按钮并且isDelaying为false表明按键为长按状态,松开按键并且isDelaying为true表明按键为短按。
下列代码为最新的MyButton。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// 自制按钮类
public class MyButton
{
public float extendingDuration = 0.2f; //extending的时间长度
public float delayingDuration = 0.2f; //delaying的时间长度
public bool isPressing = false; //正在按压
public bool onPressed = false; //刚刚按下
public bool onRelease = false; //刚刚被释放
public bool isDoubleClick = false; //双击
public bool isLongPress = false; //长按
public bool isShortPress = false; //长按
public bool isExtending = false; //释放按键后的一段时间内为true 用于双击判断
public bool isDelaying = false; //刚刚按下后的一段时间内为true 用于长按判断
private bool currentState = false; //当前状态
private bool lastState = false; //上一帧的状态
private MyTimer extendingTimer = new MyTimer(); //extending计时器
private MyTimer delayingTimer = new MyTimer(); //delaying计时器
// 更新MyButton
public void Tick(bool _input)
{
extendingTimer.Tick(Time.deltaTime);
delayingTimer.Tick(Time.deltaTime);
onPressed = false; //OnPressd只有一种情况下是true 所以每次都先设置为false
onRelease = false; //与OnPressed同理
currentState = _input; //按键的当前状态永远和对应物理按键的状态一致
isPressing = currentState; //是否被按下 按下就是true
if (currentState != lastState) //判断按键信号是否改变 改变说明刚刚按下按键或刚刚松开按键
{
if (currentState == true) //刚刚按下按键
{
onPressed = true;
StartTimer(delayingTimer, delayingDuration);
}
else //刚刚松开按键
{
onRelease = true;
StartTimer(extendingTimer, extendingDuration);
}
}
lastState = currentState; //结束时将上一帧状态更新为当前帧状态
isExtending = (extendingTimer.state == MyTimer.TIMER_STATE.RUN) ? true : false; //设置extending
isDelaying = (delayingTimer.state == MyTimer.TIMER_STATE.RUN) ? true : false; //设置delaying
isLongPress = (isPressing && !isDelaying) ? true : false; //长按判断
isShortPress = (isDelaying && onRelease) ? true : false; //短按判断
isDoubleClick = (isExtending && isPressing) ? true : false; //双击判断
}
private void StartTimer(MyTimer _timer, float _extDuration)
{
_timer.duration = _extDuration;
_timer.Go();
}
}
有了新的长按/短按信号,我们就可以直接使用。
// 翻滚/后跳
jab_roll = buttonRun_jab_roll.isShortPress;
// 冲刺
run = buttonRun_jab_roll.isLongPress;
以上是关于Unity 3D 游戏通用系统设置页面,自定义按键设置,背景虚化,图像设置,亮度对比度饱和度音量调节,分辨率窗口化,帧率垂直同步,抗锯齿,阴影质量,纹理质量设置的主要内容,如果未能解决你的问题,请参考以下文章