Unity 检测是否点击到UI元素
public static bool IfTouchUI() {
if (EventSystem.current == null) {
return false;
}
var eventData = new PointerEventData(EventSystem.current);
var mousePos = Input.mousePosition;
eventData.position = new Vector2(mousePos.x, mousePos.y);
var results = new List<RaycastResult>();
EventSystem.current.RaycastAll(eventData, results);
return results.Count > 0;
}
常用于判断点击到UI还是游戏场景内的物体
Unity 使用 Dotween 实现数字插值变化
/// <summary>
/// 数字渐变
/// </summary>
public static void GradientNumber(this Text target, int start, int end, float duration = 0.5f,
Func<int, string> func = null) {
if (start == -1) {
int.TryParse(target.text, out start);
}
if (func == null) {
func = val => val.ToString();
}
DOTween.To(() => start, value => target.text = func(value), end, duration);
}
C# 根据权重随机列表
public interface IRandomItem {
/// <summary>
/// 随机权重
/// </summary>
int Weight { get; }
}
/// <summary>
/// 根据权重随机列表, 返回命中项数组 (值越大抽中概率越大)
/// </summary>
[SuppressMessage("ReSharper", "PossibleMultipleEnumeration")]
public static T[] RandomList<T>(IEnumerable<T> list, int count = 1) where T : IRandomItem {
var result = new T[count];
var totalWeight = list.Select(item => item.Weight).Sum();
for (var i = 0; i < count; ++i) {
var random = Random.Range(0, totalWeight);
int min = 0, max = 0;
foreach (var item in list) {
max += item.Weight;
if (random >= min && random < max) {
result[i] = item;
break;
}
min = max;
}
}
return result;
}
public static T RandomOne<T>(IEnumerable<T> list) where T : IRandomItem => RandomList(list)[0];
SuppressMessage 特性只是为了隐藏 Rider 关于可能多次迭代的警告,事实上不会有这个问题。
随机的数据类需继承 IRandomItem
接口,并实现 Weight
属性。
常用于英雄抽卡,幸运转盘,抽奖池等;需要根据权重随机抽取元素的模块。
C# String分割为数组
/// <summary>
/// string分割为数组, 默认以','分割
/// </summary>
public static T[] Str2Arr<T>(this string str, Func<string, T> func, char splitChar = ',') {
return str.Split(splitChar).Select(func).ToArray();
}
可传入 func 指定分割后的数组类型,转换为 int 则需传入 int.Parse
。
BigInteger 类型的格式化显示
/// <summary>
/// 数字格式化
/// </summary>
public static string FormatBigInt(this BigInteger bigInt) {
var bigIntStr = bigInt.ToString();
var digit = bigIntStr.Length; // 位数
if (digit <= 3) {
return bigIntStr;
}
digit -= 1;
var prefix = digit % 3 + 1; // 小数点前的位数
return bigIntStr.Substring(0, prefix + 2).Insert(prefix, ".") + GetA_Z(digit / 3);
}
/// <summary>
/// 获取26个字母
/// </summary>
/// <param name="num">1是a, 2是b</param>
private static char GetA_Z(int num) => (char) (96 + num);
当游戏数值非常大,超出 decimal 和 double 的精度时,需要使用 BigInteger 类型。
进行乘除运算时使用 double,加减以及存储时使用 BigInteger。
格式化以千进位,例如:1234=1.23a。
C# 删除栈中的指定元素
/// <summary>
/// 删除栈中的指定元素
/// </summary>
/// <returns>返回是否删除, false代表栈中无此元素</returns>
public static bool RemoveAny<T>(this Stack<T> stack, T element) {
var topElement = stack.Pop();
if (Equals(topElement, element)) {
return true;
}
var remove = false;
if (stack.Count != 0) {
remove = stack.RemoveAny(element);
}
stack.Push(topElement);
return remove;
}
C# 简单树结构实现
using System;
using System.Collections.Generic;
/// <summary>
/// 简单的树结构
/// </summary>
public class TreeNode<T> {
public readonly T Value;
public TreeNode<T> Parent { get; private set; }
public List<TreeNode<T>> Children { get; private set; }
/// <summary>
/// 是否是根节点
/// </summary>
public bool IsRoot => Parent == null;
/// <summary>
/// 是否是叶子节点
/// </summary>
public bool IsLeaf => Children == null;
public TreeNode(T value) {
Value = value;
}
public TreeNode<T> SetParent(T value) {
var node = new TreeNode<T>(value);
SetParent(node);
return node;
}
public void SetParent(TreeNode<T> node) {
if (!IsRoot) {
Parent.RemoveChildren(this);
}
node.AddChildren(this);
}
public TreeNode<T> AddChildren(T value) {
var node = new TreeNode<T>(value);
AddChildren(node);
return node;
}
public void AddChildren(TreeNode<T> node) {
if (IsLeaf) {
Children = new List<TreeNode<T>>();
}
Children.Add(node);
node.Parent = this;
}
public void RemoveChildren(TreeNode<T> node) {
if (IsLeaf) {
return;
}
Children.Remove(node);
if (Children.Count == 0) {
Children = null;
}
}
/// <summary>
/// 递归查询孩子节点
/// </summary>
private static TreeNode<T> FindChildren(TreeNode<T> node, Func<T, bool> func) {
if (func(node.Value)) {
return node;
}
if (node.IsLeaf) {
return null;
}
foreach (var child in node.Children) {
var find = FindChildren(child, func);
if (find != null) {
return find;
}
}
return null;
}
public TreeNode<T> FindChildren(Func<T, bool> func) => FindChildren(this, func);
public TreeNode<T> FindParent(Func<T, bool> func) {
var result = this;
while (!result.IsRoot) {
result = result.Parent;
if (func(result.Value)) {
return result;
}
}
return null;
}
}