1
This commit is contained in:
@@ -63,6 +63,11 @@ namespace BITKit
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
ItemQuality Quality { get; }
|
ItemQuality Quality { get; }
|
||||||
bool CopyItemsFrom(IBasicItem item);
|
bool CopyItemsFrom(IBasicItem item);
|
||||||
|
/// <summary>
|
||||||
|
/// 价值
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
int Value=>10;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 可配置化物品,通常用于配置
|
/// 可配置化物品,通常用于配置
|
||||||
@@ -84,6 +89,7 @@ namespace BITKit
|
|||||||
public string AddressablePath { get; set; }
|
public string AddressablePath { get; set; }
|
||||||
public string Description;
|
public string Description;
|
||||||
public ItemQuality Quality;
|
public ItemQuality Quality;
|
||||||
|
public int Value { get; set; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 本地属性
|
/// 本地属性
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -122,6 +128,7 @@ namespace BITKit
|
|||||||
|
|
||||||
public bool CopyItemsFrom(IBasicItem item)
|
public bool CopyItemsFrom(IBasicItem item)
|
||||||
{
|
{
|
||||||
|
Value = item.Value;
|
||||||
Id=item.Id;
|
Id=item.Id;
|
||||||
Name = item.Name;
|
Name = item.Name;
|
||||||
AddressablePath = item.AddressablePath;
|
AddressablePath = item.AddressablePath;
|
||||||
|
@@ -75,6 +75,21 @@ namespace BITKit
|
|||||||
/// 已重构Items的回调
|
/// 已重构Items的回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action<IBasicItemContainer> OnRebuild;
|
event Action<IBasicItemContainer> OnRebuild;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否已完成物品交换,例如false就是开始交换物品true就是已完成交换物品,可以处理物品了
|
||||||
|
/// </summary>
|
||||||
|
event Action<bool> OnRelease;
|
||||||
|
/// <summary>
|
||||||
|
/// 添加挂起句柄
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
void AddHandle(int id);
|
||||||
|
/// <summary>
|
||||||
|
/// 移除挂起句柄
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
void RemoveHandle(int id);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -7,6 +7,17 @@ namespace BITKit
|
|||||||
{
|
{
|
||||||
public static class MathE
|
public static class MathE
|
||||||
{
|
{
|
||||||
|
public static int GetHash<T>(IEnumerable<T> self)
|
||||||
|
{
|
||||||
|
var hash = 0;
|
||||||
|
foreach (var x in self)
|
||||||
|
{
|
||||||
|
if (x is not null)
|
||||||
|
hash += x.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
public static bool IndexInRange<T>(this IEnumerable<T> self, int index)
|
public static bool IndexInRange<T>(this IEnumerable<T> self, int index)
|
||||||
{
|
{
|
||||||
return index >= 0 && index < self.Count();
|
return index >= 0 && index < self.Count();
|
||||||
|
8
Src/Core/Probability.meta
Normal file
8
Src/Core/Probability.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e517c312e735e1042b911efc79deb1f6
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
14
Src/Core/Probability/BITKit.Probability.asmdef
Normal file
14
Src/Core/Probability/BITKit.Probability.asmdef
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "BITKit.Probability",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": true
|
||||||
|
}
|
7
Src/Core/Probability/BITKit.Probability.asmdef.meta
Normal file
7
Src/Core/Probability/BITKit.Probability.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2f7d7f857f30f484ea163931f3bc4e0a
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
50
Src/Core/Probability/IProbability.cs
Normal file
50
Src/Core/Probability/IProbability.cs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace BITKit.Probability
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 概率属性
|
||||||
|
/// </summary>
|
||||||
|
public interface IProbabilityProperty
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 概率服务
|
||||||
|
/// </summary>
|
||||||
|
public interface IProbabilityService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 根据概率属性获取值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="properties"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
object GetValueObject(params IProbabilityProperty[] properties);
|
||||||
|
/// <summary>
|
||||||
|
/// 根据概率属性获取值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="properties"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
object[] GetValuesObject(params IProbabilityProperty[] properties);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// 泛型概率服务
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public interface IProbabilityService<T>:IProbabilityService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 根据概率属性获取值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="properties"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
T GetValue(params IProbabilityProperty[] properties);
|
||||||
|
/// <summary>
|
||||||
|
/// 根据概率属性获取值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="properties"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
T[] GetValues(params IProbabilityProperty[] properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: d6c28a6107497be44bfecb5e31b960c5
|
guid: 8e4f1cbf25a4f494d89fc3831dbc82ab
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
@@ -70,87 +70,84 @@ namespace BITKit
|
|||||||
{
|
{
|
||||||
foreach (var x in factory)
|
foreach (var x in factory)
|
||||||
{
|
{
|
||||||
AddPropertyInternal(x);
|
properties.Add(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Dictionary<string, object> properties=new();
|
private readonly List<object> properties=new();
|
||||||
public T GetProperty<T>()
|
public T GetProperty<T>()
|
||||||
{
|
{
|
||||||
return (T)properties[typeof(T).FullName];
|
return properties.OfType<T>().First();
|
||||||
}
|
}
|
||||||
public void SetProperty<T>(T value)
|
public void SetProperty<T>(T value)
|
||||||
{
|
{
|
||||||
properties.Insert(typeof(T).FullName, value);
|
for (var i = 0; i < properties.Count; i++)
|
||||||
|
{
|
||||||
|
if (properties[i] is T)
|
||||||
|
properties[i] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public bool Contains<T>()
|
public bool Contains<T>()
|
||||||
{
|
{
|
||||||
return properties.ContainsKey(typeof(T).FullName);
|
return properties.OfType<T>().FirstOrDefault() is not null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetOrCreateProperty<T>()
|
public T GetOrCreateProperty<T>()
|
||||||
{
|
{
|
||||||
return GetOrAddProperty(Activator.CreateInstance<T>);
|
return GetOrAddProperty(Activator.CreateInstance<T>);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T GetOrAddProperty<T>(Func<T> addFactory)
|
public T GetOrAddProperty<T>(Func<T> addFactory)
|
||||||
{
|
{
|
||||||
if (properties.TryGetValue(typeof(T).FullName, out var x))
|
foreach (var obj in properties)
|
||||||
{
|
{
|
||||||
return (T)x;
|
if (obj is T t) return t;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AddPropertyInternal(x =addFactory.Invoke());
|
|
||||||
//properties.Add(typeof(T).FullName, x = addFactory.Invoke());
|
|
||||||
return (T)x;
|
|
||||||
}
|
}
|
||||||
|
T x;
|
||||||
|
properties.Add(x = addFactory.Invoke());
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool TryGetProperty<T>(out T value)
|
public bool TryGetProperty<T>(out T value)
|
||||||
{
|
{
|
||||||
if (properties.TryGetValue(typeof(T).FullName, out var x))
|
try
|
||||||
{
|
{
|
||||||
value = (T)x;
|
value = properties.OfType<T>().First();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
catch (InvalidOperationException)
|
||||||
{
|
{
|
||||||
value=default(T);
|
value = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public bool TryRemoveProperty<T>()
|
public bool TryRemoveProperty<T>()
|
||||||
{
|
{
|
||||||
foreach (var pair in properties.Where(x=>x.Value is T))
|
var removed=false;
|
||||||
|
foreach (var value in properties.OfType<T>().ToArray())
|
||||||
{
|
{
|
||||||
properties.Remove(pair.Key);
|
properties.Remove(value);
|
||||||
return true;
|
removed = true;
|
||||||
}
|
}
|
||||||
// if(properties.TryGetValue(typeof(T).FullName, out var x))
|
// if(properties.TryGetValue(typeof(T).FullName, out var x))
|
||||||
// {
|
// {
|
||||||
// properties.Remove(typeof(T).Name);
|
// properties.Remove(typeof(T).Name);
|
||||||
// return true;
|
// return true;
|
||||||
// }
|
// }
|
||||||
return false;
|
return removed;
|
||||||
}
|
}
|
||||||
public bool TrySetProperty<T>(T value)
|
public bool TrySetProperty<T>(T value)
|
||||||
{
|
{
|
||||||
bool result = false;
|
var current = properties.OfType<T>().FirstOrDefault();
|
||||||
foreach (var pair in properties.Where(x=>x.Value is T).ToArray())
|
if (current is not null)
|
||||||
{
|
{
|
||||||
properties[pair.Key] = value;
|
properties.Remove(current);
|
||||||
result = true;
|
return true;
|
||||||
}
|
}
|
||||||
return result;
|
properties.Add(value);
|
||||||
// if (properties.TryGetValue(typeof(T).FullName, out var x))
|
return false;
|
||||||
// {
|
|
||||||
// properties[typeof(T).FullName] = value;
|
|
||||||
// return true;
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
public object[] GetProperties()=>properties.Values.Distinct().ToArray();
|
|
||||||
|
public object[] GetProperties() => properties.ToArray();
|
||||||
|
|
||||||
public void Read(BinaryReader r)
|
public void Read(BinaryReader r)
|
||||||
{
|
{
|
||||||
@@ -174,23 +171,8 @@ namespace BITKit
|
|||||||
public bool CopyPropertiesFrom(IPropertable propertable)
|
public bool CopyPropertiesFrom(IPropertable propertable)
|
||||||
{
|
{
|
||||||
ClearProperties();
|
ClearProperties();
|
||||||
foreach (var x in propertable.GetProperties())
|
properties.AddRange( propertable.GetProperties());;
|
||||||
{
|
|
||||||
AddPropertyInternal(x);
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
private void AddPropertyInternal(object value)
|
|
||||||
{
|
|
||||||
if (value is ICloneable cloneable)
|
|
||||||
{
|
|
||||||
value = cloneable.Clone();
|
|
||||||
}
|
|
||||||
properties.Set(value.GetType().FullName, value);
|
|
||||||
foreach (var att in value.GetType().GetCustomAttributes<CustomTypeAttribute>())
|
|
||||||
{
|
|
||||||
properties.Set(att.Type!.FullName, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -2,6 +2,7 @@ namespace BITKit
|
|||||||
{
|
{
|
||||||
public interface ITag
|
public interface ITag
|
||||||
{
|
{
|
||||||
|
int Hash { get; }
|
||||||
string[] GetTags();
|
string[] GetTags();
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -145,6 +145,13 @@ namespace BITKit
|
|||||||
{
|
{
|
||||||
value = _directDirection.Get(key);
|
value = _directDirection.Get(key);
|
||||||
}
|
}
|
||||||
|
public T GetOrAddDirect<T>(int key,Func<T> factory)
|
||||||
|
{
|
||||||
|
if (_directDirection.TryGetValue(key, out var v)) return v is T t ? t : default;
|
||||||
|
var value = factory.Invoke();
|
||||||
|
_directDirection.Add(key, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
public void GetDirect<T>(int key,out T value)
|
public void GetDirect<T>(int key,out T value)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@@ -26,6 +26,7 @@ RenderTexture:
|
|||||||
m_UseDynamicScale: 0
|
m_UseDynamicScale: 0
|
||||||
m_BindMS: 0
|
m_BindMS: 0
|
||||||
m_EnableCompatibleFormat: 1
|
m_EnableCompatibleFormat: 1
|
||||||
|
m_EnableRandomWrite: 0
|
||||||
m_TextureSettings:
|
m_TextureSettings:
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
m_FilterMode: 1
|
m_FilterMode: 1
|
||||||
|
@@ -1,28 +0,0 @@
|
|||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
using BITKit.Sensors;
|
|
||||||
namespace BITKit.Entities
|
|
||||||
{
|
|
||||||
public class EntityAudioObject : EntityBehavior, IAudioObject
|
|
||||||
{
|
|
||||||
float volume;
|
|
||||||
public override void OnStart()
|
|
||||||
{
|
|
||||||
UnityEntity.AddListener<AudioSO>(OnAuioSO);
|
|
||||||
}
|
|
||||||
public override void OnFixedUpdate(float deltaTime)
|
|
||||||
{
|
|
||||||
volume = Mathf.Lerp(volume, 0, deltaTime);
|
|
||||||
}
|
|
||||||
public float GetVolume()
|
|
||||||
{
|
|
||||||
return volume;
|
|
||||||
}
|
|
||||||
void OnAuioSO(AudioSO so)
|
|
||||||
{
|
|
||||||
if (so.distance > volume)
|
|
||||||
volume = so.distance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using BITKit.Mod;
|
using BITKit.Mod;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@@ -15,6 +16,7 @@ namespace BITKit.Animations
|
|||||||
public class ScriptableMotionMatchingService : MonoBehaviour,IMotionMatchingService
|
public class ScriptableMotionMatchingService : MonoBehaviour,IMotionMatchingService
|
||||||
{
|
{
|
||||||
internal static ScriptableMotionMatchingService Singleton { get; private set; }
|
internal static ScriptableMotionMatchingService Singleton { get; private set; }
|
||||||
|
internal static readonly ConcurrentDictionary<int, IMotionMatchingObject> Cache = new();
|
||||||
|
|
||||||
private ObjectMatcher<string,IMotionMatchingObject> _objects;
|
private ObjectMatcher<string,IMotionMatchingObject> _objects;
|
||||||
|
|
||||||
@@ -40,16 +42,23 @@ namespace BITKit.Animations
|
|||||||
|
|
||||||
public bool TryMatch(out IMotionMatchingObject value, string[] key)
|
public bool TryMatch(out IMotionMatchingObject value, string[] key)
|
||||||
{
|
{
|
||||||
if (_objects.TryMatch(out value, key))
|
value = Cache.GetOrAdd(MathE.GetHash(key),Add);
|
||||||
|
return value is not null;
|
||||||
|
|
||||||
|
IMotionMatchingObject Add(int hash)
|
||||||
{
|
{
|
||||||
return true;
|
if (_objects.TryMatch(out IMotionMatchingObject x, key) is false)
|
||||||
|
{
|
||||||
|
BIT4Log.Log<ScriptableMotionMatchingService>($"找不到对应的MotionMatchingObject:{string.Join(",", key)}");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
}
|
}
|
||||||
BIT4Log.Log<ScriptableMotionMatchingService>($"找不到对应的MotionMatchingObject:{string.Join(",", key)}");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Rebuild()
|
private void Rebuild()
|
||||||
{
|
{
|
||||||
|
Cache.Clear();
|
||||||
var list = new List<ScriptableMotionMatchingObject>();
|
var list = new List<ScriptableMotionMatchingObject>();
|
||||||
var tags = new []{nameof(IMotionMatchingObject)};
|
var tags = new []{nameof(IMotionMatchingObject)};
|
||||||
foreach (var x in YooAssets.GetAssetInfos(tags))
|
foreach (var x in YooAssets.GetAssetInfos(tags))
|
||||||
|
@@ -25,6 +25,7 @@ namespace BITKit
|
|||||||
if (UnityEngine.Physics.Raycast(root.position, root.forward, out var raycastHit, distance, layerMask))
|
if (UnityEngine.Physics.Raycast(root.position, root.forward, out var raycastHit, distance, layerMask))
|
||||||
{
|
{
|
||||||
var collider = raycastHit.collider;
|
var collider = raycastHit.collider;
|
||||||
|
if (collider.isTrigger) return false;
|
||||||
switch (collider)
|
switch (collider)
|
||||||
{
|
{
|
||||||
case MeshCollider meshCollider:
|
case MeshCollider meshCollider:
|
||||||
|
@@ -4,7 +4,7 @@ using System.Collections.Generic;
|
|||||||
using BITKit.Core.Tuple;
|
using BITKit.Core.Tuple;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace BITKit.Physics
|
namespace BITKit
|
||||||
{
|
{
|
||||||
[Serializable]
|
[Serializable]
|
||||||
public class JointConfigure
|
public class JointConfigure
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using BITKit.Events;
|
using BITKit.Events;
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace BITKit.Physics
|
namespace BITKit
|
||||||
{
|
{
|
||||||
public class Prop_Physics : MonoBehaviour
|
public class Prop_Physics : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
@@ -41,6 +41,15 @@ namespace BITKit.SceneManagement
|
|||||||
/// 场景加载完成的回调
|
/// 场景加载完成的回调
|
||||||
/// </summary>
|
/// </summary>
|
||||||
event Action<string> OnSceneLoaded;
|
event Action<string> OnSceneLoaded;
|
||||||
|
/// <summary>
|
||||||
|
/// 注册加载任务
|
||||||
|
/// </summary>
|
||||||
|
void RegisterLoadTaskAsync(Func<UniTask> task);
|
||||||
|
/// <summary>
|
||||||
|
/// 注销加载任务
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task"></param>
|
||||||
|
void UnRegisterLoadTaskAsync(Func<UniTask> task);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当开始卸载场景时
|
/// 当开始卸载场景时
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -89,6 +98,16 @@ namespace BITKit.SceneManagement
|
|||||||
remove => _sceneServiceImplementation.OnSceneLoaded -= value;
|
remove => _sceneServiceImplementation.OnSceneLoaded -= value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void RegisterLoadTaskAsync(Func<UniTask> task)
|
||||||
|
{
|
||||||
|
_sceneServiceImplementation.RegisterLoadTaskAsync(task);
|
||||||
|
}
|
||||||
|
public void UnRegisterLoadTaskAsync(Func<UniTask> task)
|
||||||
|
{
|
||||||
|
_sceneServiceImplementation.UnRegisterLoadTaskAsync(task);
|
||||||
|
}
|
||||||
|
|
||||||
public event Action<string> OnUnloadScene
|
public event Action<string> OnUnloadScene
|
||||||
{
|
{
|
||||||
add => _sceneServiceImplementation1.OnUnloadScene += value;
|
add => _sceneServiceImplementation1.OnUnloadScene += value;
|
||||||
|
@@ -58,6 +58,16 @@ namespace BITKit.SceneManagement
|
|||||||
remove => SceneService.OnSceneLoaded -= value;
|
remove => SceneService.OnSceneLoaded -= value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void RegisterLoadTaskAsync(Func<UniTask> task)
|
||||||
|
{
|
||||||
|
_sceneServiceImplementation.RegisterLoadTaskAsync(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnRegisterLoadTaskAsync(Func<UniTask> task)
|
||||||
|
{
|
||||||
|
_sceneServiceImplementation.UnRegisterLoadTaskAsync(task);
|
||||||
|
}
|
||||||
|
|
||||||
public event Action<string> OnUnloadScene
|
public event Action<string> OnUnloadScene
|
||||||
{
|
{
|
||||||
add => _sceneServiceImplementation.OnUnloadScene += value;
|
add => _sceneServiceImplementation.OnUnloadScene += value;
|
||||||
@@ -198,9 +208,15 @@ namespace BITKit.SceneManagement
|
|||||||
OnSceneLoadProgress?.Invoke(sceneName, progress);
|
OnSceneLoadProgress?.Invoke(sceneName, progress);
|
||||||
}
|
}
|
||||||
LoadedObjects.Add(sceneName, handle.SceneObject);
|
LoadedObjects.Add(sceneName, handle.SceneObject);
|
||||||
|
|
||||||
OnSceneLoadProgress?.Invoke(sceneName, 1);
|
OnSceneLoadProgress?.Invoke(sceneName, 1);
|
||||||
await Task.Delay(384, cancellationToken);
|
await Task.Delay(384, cancellationToken);
|
||||||
|
|
||||||
|
foreach (var x in _onSceneLoadedAsyncList.ToArray())
|
||||||
|
{
|
||||||
|
await x.Invoke();
|
||||||
|
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||||
|
}
|
||||||
|
|
||||||
OnSceneLoaded?.Invoke(sceneName);
|
OnSceneLoaded?.Invoke(sceneName);
|
||||||
stopwatchWatcher.Stop();
|
stopwatchWatcher.Stop();
|
||||||
// if (activateOnLoad is false)
|
// if (activateOnLoad is false)
|
||||||
@@ -252,6 +268,16 @@ namespace BITKit.SceneManagement
|
|||||||
remove => OnSceneLoaded -= value;
|
remove => OnSceneLoaded -= value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly List<Func<UniTask>> _onSceneLoadedAsyncList=new();
|
||||||
|
public void RegisterLoadTaskAsync(Func<UniTask> task)
|
||||||
|
{
|
||||||
|
_onSceneLoadedAsyncList.Add(task);
|
||||||
|
}
|
||||||
|
public void UnRegisterLoadTaskAsync(Func<UniTask> task)
|
||||||
|
{
|
||||||
|
_onSceneLoadedAsyncList.Remove(task);
|
||||||
|
}
|
||||||
|
|
||||||
public event Action<string> OnUnloadScene;
|
public event Action<string> OnUnloadScene;
|
||||||
public event Action<string> OnSceneUnloaded;
|
public event Action<string> OnSceneUnloaded;
|
||||||
}
|
}
|
||||||
|
@@ -1,49 +1,49 @@
|
|||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Pool;
|
using UnityEngine.Pool;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using UnityEditor.Search;
|
||||||
|
|
||||||
namespace BITKit.Sensors
|
namespace BITKit.Sensors
|
||||||
{
|
{
|
||||||
public interface IAudioObject
|
public interface IAudioObject
|
||||||
{
|
{
|
||||||
float GetVolume();
|
float GetVolume();
|
||||||
}
|
}
|
||||||
public class AudioSensor : Sensor
|
public class AudioSensor : MonoBehaviour,ISensor
|
||||||
{
|
{
|
||||||
[Header(Constant.Header.Settings)]
|
[Header(Constant.Header.Settings)]
|
||||||
public float radius;
|
[SerializeField] private bool autoUpdate;
|
||||||
[Header(Constant.Header.InternalVariables)]
|
[SerializeField]private float radius;
|
||||||
IAudioObject currentAudioObject;
|
private readonly CacheList<Transform> cache = new();
|
||||||
Collider currentCollider;
|
private void OnEnable()
|
||||||
Collider[] colliders = new Collider[32];
|
|
||||||
public override IEnumerable<Transform> Get() => detected;
|
|
||||||
public override UniTask Execute()
|
|
||||||
{
|
{
|
||||||
var cacheList = ListPool<Transform>.Get();
|
Id = GetInstanceID();
|
||||||
for (int i = 0; i < Physics.OverlapSphereNonAlloc(transform.position, radius, colliders, detectLayer); i++)
|
SensorQueue.Register(Id,this);
|
||||||
|
}
|
||||||
|
private void OnDisable()
|
||||||
|
{
|
||||||
|
SensorQueue.UnRegister(Id);
|
||||||
|
}
|
||||||
|
public UniTask Execute(float delta)
|
||||||
|
{
|
||||||
|
var position = transform.position;
|
||||||
|
cache.Clear();
|
||||||
|
foreach (var x in AudioSensorService.QuadtreeRoot.Find(new Bounds(position, Vector3.one * radius)))
|
||||||
{
|
{
|
||||||
currentCollider = colliders[i];
|
var distance = Vector3.Distance(position, x.Position);
|
||||||
if (IsValid(currentCollider))
|
if(distance>radius) continue;
|
||||||
{
|
cache.Add(x.Transform);
|
||||||
cacheList.Add(currentCollider.transform);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
detected = cacheList.ToArray();
|
|
||||||
ListPool<Transform>.Release(cacheList);
|
|
||||||
return UniTask.CompletedTask;
|
return UniTask.CompletedTask;
|
||||||
}
|
}
|
||||||
public override bool IsValid(Collider _collider)
|
public int Id { get; set; }
|
||||||
{
|
public IEnumerable<Transform> Get() => cache.ValueArray;
|
||||||
if (ignoreColliders.Contains(_collider) is false)
|
public bool IsValid(Collider _collider) => false;
|
||||||
if (Vector3.Distance(transform.position, _collider.transform.position) <= radius)
|
public float GetDistance() => radius;
|
||||||
if (_collider.TryGetComponent<IAudioObject>(out currentAudioObject))
|
public bool AutoUpdate=>autoUpdate;
|
||||||
{
|
|
||||||
return currentAudioObject.GetVolume() >= 1;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
public override float GetDistance() => radius;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
67
Src/Unity/Scripts/Sensor/AudioSensorService.cs
Normal file
67
Src/Unity/Scripts/Sensor/AudioSensorService.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
|
using kcp2k;
|
||||||
|
using Quadtree;
|
||||||
|
using Quadtree.Items;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.Pool;
|
||||||
|
|
||||||
|
namespace BITKit.Sensors
|
||||||
|
{
|
||||||
|
public class AudioSensorService : MonoBehaviour
|
||||||
|
{
|
||||||
|
public class AudioSensorData:IItem<AudioSensorData,Node<AudioSensorData>>
|
||||||
|
{
|
||||||
|
public int Id;
|
||||||
|
public Vector3 Position;
|
||||||
|
public float Radius;
|
||||||
|
public Transform Transform;
|
||||||
|
public Bounds Bounds;
|
||||||
|
public ITag Tag;
|
||||||
|
public Bounds GetBounds() => Bounds;
|
||||||
|
public Node<AudioSensorData> ParentNode { get; set; }
|
||||||
|
public void QuadTree_Root_Initialized(IQuadtreeRoot<AudioSensorData, Node<AudioSensorData>> root){}
|
||||||
|
}
|
||||||
|
internal static readonly QuadtreeRoot<AudioSensorData, Node<AudioSensorData>> QuadtreeRoot =
|
||||||
|
new(default, Vector3.one * 2048);
|
||||||
|
|
||||||
|
private static Pool<AudioSensorData> pool = new(()=>new(), x=>{}, 1000);
|
||||||
|
private static int count;
|
||||||
|
public static async void MakeNoise(Vector3 position,Transform transform)
|
||||||
|
{
|
||||||
|
var data = pool.Take();
|
||||||
|
data.Id = count++;
|
||||||
|
data.Position = position;
|
||||||
|
data.Transform = transform;
|
||||||
|
data.Bounds = new Bounds(position, Vector3.one *1);
|
||||||
|
data.Tag = transform.GetComponent<ITag>();
|
||||||
|
QuadtreeRoot.Insert(data);
|
||||||
|
await UniTask.Delay(3000);
|
||||||
|
if (disposed) return;
|
||||||
|
QuadtreeRoot.Remove(data);
|
||||||
|
pool.Return(data);
|
||||||
|
}
|
||||||
|
private static bool disposed;
|
||||||
|
[SerializeReference, SubclassSelector] private ITicker ticker;
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
disposed = false;
|
||||||
|
ticker.Add(OnTick);
|
||||||
|
destroyCancellationToken.Register(Dispose);
|
||||||
|
pool.Clear();
|
||||||
|
}
|
||||||
|
private void Dispose()
|
||||||
|
{
|
||||||
|
ticker.Remove(OnTick);
|
||||||
|
disposed = true;
|
||||||
|
QuadtreeRoot.Clear();
|
||||||
|
}
|
||||||
|
private void OnTick(float obj)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
11
Src/Unity/Scripts/Sensor/AudioSensorService.cs.meta
Normal file
11
Src/Unity/Scripts/Sensor/AudioSensorService.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: db1536b0b240b724f8741f900b2da455
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@@ -9,7 +9,8 @@
|
|||||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||||
"GUID:be17a8778dbfe454890ed8279279e153",
|
"GUID:be17a8778dbfe454890ed8279279e153",
|
||||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||||
"GUID:9400d40641bab5b4a9702f65bf5c6eb5"
|
"GUID:9400d40641bab5b4a9702f65bf5c6eb5",
|
||||||
|
"GUID:1193c2664d97cc049a6e4c486c6bce71"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
@@ -17,6 +17,7 @@ namespace BITKit.Sensors
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ISensor
|
public interface ISensor
|
||||||
{
|
{
|
||||||
|
int Id { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自动更新
|
/// 自动更新
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -45,7 +46,7 @@ namespace BITKit.Sensors
|
|||||||
/// 传感器执行检测
|
/// 传感器执行检测
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
UniTask Execute();
|
UniTask Execute(float delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable]
|
[Serializable]
|
||||||
@@ -53,6 +54,8 @@ namespace BITKit.Sensors
|
|||||||
{
|
{
|
||||||
[SerializeField] private GameObject gameObject;
|
[SerializeField] private GameObject gameObject;
|
||||||
private ISensor _sensorImplementation => gameObject.GetComponent<ISensor>();
|
private ISensor _sensorImplementation => gameObject.GetComponent<ISensor>();
|
||||||
|
public int Id => _sensorImplementation.Id;
|
||||||
|
|
||||||
public IEnumerable<Transform> Get()
|
public IEnumerable<Transform> Get()
|
||||||
{
|
{
|
||||||
return _sensorImplementation.Get();
|
return _sensorImplementation.Get();
|
||||||
@@ -67,10 +70,9 @@ namespace BITKit.Sensors
|
|||||||
{
|
{
|
||||||
return _sensorImplementation.GetDistance();
|
return _sensorImplementation.GetDistance();
|
||||||
}
|
}
|
||||||
|
public UniTask Execute(float delta)
|
||||||
public UniTask Execute()
|
|
||||||
{
|
{
|
||||||
return _sensorImplementation.Execute();
|
return _sensorImplementation.Execute(delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[System.Serializable]
|
[System.Serializable]
|
||||||
@@ -78,6 +80,8 @@ namespace BITKit.Sensors
|
|||||||
{
|
{
|
||||||
[SerializeField] private MonoBehaviour monoBehaviour;
|
[SerializeField] private MonoBehaviour monoBehaviour;
|
||||||
private ISensor _sensorImplementation=>monoBehaviour as ISensor;
|
private ISensor _sensorImplementation=>monoBehaviour as ISensor;
|
||||||
|
public int Id => _sensorImplementation.Id;
|
||||||
|
|
||||||
public IEnumerable<Transform> Get()
|
public IEnumerable<Transform> Get()
|
||||||
{
|
{
|
||||||
return _sensorImplementation.Get();
|
return _sensorImplementation.Get();
|
||||||
@@ -93,9 +97,9 @@ namespace BITKit.Sensors
|
|||||||
return _sensorImplementation.GetDistance();
|
return _sensorImplementation.GetDistance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniTask Execute()
|
public UniTask Execute(float delta)
|
||||||
{
|
{
|
||||||
return _sensorImplementation.Execute();
|
return _sensorImplementation.Execute(delta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public abstract class Sensor : MonoBehaviour, ISensor
|
public abstract class Sensor : MonoBehaviour, ISensor
|
||||||
@@ -106,16 +110,15 @@ namespace BITKit.Sensors
|
|||||||
[Header(Constant.Header.Gameobjects)]
|
[Header(Constant.Header.Gameobjects)]
|
||||||
public Collider[] ignoreColliders;
|
public Collider[] ignoreColliders;
|
||||||
[Header(Constant.Header.InternalVariables)]
|
[Header(Constant.Header.InternalVariables)]
|
||||||
[NonSerialized]
|
[SerializeField,ReadOnly]
|
||||||
public Transform[] detected = Array.Empty<Transform>();
|
public Transform[] detected = Array.Empty<Transform>();
|
||||||
public abstract IEnumerable<Transform> Get();
|
public abstract IEnumerable<Transform> Get();
|
||||||
public abstract bool IsValid(Collider _collider);
|
public abstract bool IsValid(Collider _collider);
|
||||||
public abstract UniTask Execute();
|
|
||||||
public abstract float GetDistance();
|
public abstract float GetDistance();
|
||||||
|
public virtual UniTask Execute(float delta)=>UniTask.CompletedTask;
|
||||||
|
public int Id { get; private set; }
|
||||||
bool ISensor.AutoUpdate => autoUpdate;
|
bool ISensor.AutoUpdate => autoUpdate;
|
||||||
|
|
||||||
protected int Id;
|
|
||||||
protected Transform Transform;
|
protected Transform Transform;
|
||||||
|
|
||||||
protected virtual void OnEnable()
|
protected virtual void OnEnable()
|
||||||
|
16
Src/Unity/Scripts/Sensor/Core/SensorTarget.cs
Normal file
16
Src/Unity/Scripts/Sensor/Core/SensorTarget.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace BITKit.Sensors
|
||||||
|
{
|
||||||
|
public interface ISensorTarget
|
||||||
|
{
|
||||||
|
public int Id { get; }
|
||||||
|
Bounds Bounds { get; }
|
||||||
|
Transform Transform { get; }
|
||||||
|
void Detected(float weight,ISensor sensor,object sender);
|
||||||
|
event Action<float, ISensor, object> OnDetected;
|
||||||
|
}
|
||||||
|
}
|
11
Src/Unity/Scripts/Sensor/Core/SensorTarget.cs.meta
Normal file
11
Src/Unity/Scripts/Sensor/Core/SensorTarget.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d6b2f04f438f7bd4c812fb6441a5ca4a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@@ -12,7 +12,7 @@ namespace BITKit.Sensors
|
|||||||
public override IEnumerable<Transform> Get()=>sensors.SelectMany(x => x.Get());
|
public override IEnumerable<Transform> Get()=>sensors.SelectMany(x => x.Get());
|
||||||
public override bool IsValid(Collider _collider) => sensors.Any(x => x.IsValid(_collider) is false) is false;
|
public override bool IsValid(Collider _collider) => sensors.Any(x => x.IsValid(_collider) is false) is false;
|
||||||
public override float GetDistance() => sensors.Min(x => x.GetDistance());
|
public override float GetDistance() => sensors.Min(x => x.GetDistance());
|
||||||
public override UniTask Execute() => UniTask.WhenAll(sensors.Select(x => x.Execute()));
|
public override UniTask Execute(float delta) => UniTask.WhenAll(sensors.Select(x => x.Execute(delta)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -7,24 +7,25 @@ using Cysharp.Threading.Tasks;
|
|||||||
using UnityEngine.Jobs;
|
using UnityEngine.Jobs;
|
||||||
using UnityEngine.Pool;
|
using UnityEngine.Pool;
|
||||||
using UnityEngine.Profiling;
|
using UnityEngine.Profiling;
|
||||||
|
using Physics=UnityEngine.Physics;
|
||||||
|
|
||||||
namespace BITKit.Sensors
|
namespace BITKit.Sensors
|
||||||
{
|
{
|
||||||
public class RangeSensor : Sensor
|
public class RangeSensor : Sensor
|
||||||
{
|
{
|
||||||
[Header(Constant.Header.Settings)]
|
[Header(Constant.Header.Settings)] public float radius;
|
||||||
public float radius;
|
|
||||||
public int fov;
|
public int fov;
|
||||||
public bool requireSight;
|
public bool requireSight;
|
||||||
|
|
||||||
[Header(Constant.Header.Settings)]
|
|
||||||
public LayerMask blockLayer;
|
|
||||||
[Header(Constant.Header.InternalVariables)]
|
|
||||||
private FrameUpdate frameUpdater;
|
|
||||||
private readonly Collider[] colliders = new Collider[32];
|
|
||||||
private RaycastHit[] hits;
|
|
||||||
|
|
||||||
private bool isExecuting;
|
[Header(Constant.Header.Settings)] public LayerMask blockLayer;
|
||||||
|
|
||||||
|
[Header(Constant.Header.Debug)] [Header(Constant.Header.InternalVariables)]
|
||||||
|
private FrameUpdate frameUpdater;
|
||||||
|
|
||||||
|
private readonly Collider[] colliders = new Collider[32];
|
||||||
|
private RaycastHit[] hits = new RaycastHit[32];
|
||||||
|
private readonly HashSet<int> tempHashSet = new();
|
||||||
|
|
||||||
public override IEnumerable<Transform> Get()
|
public override IEnumerable<Transform> Get()
|
||||||
{
|
{
|
||||||
if (!_detectedDoubleBuffer.TryGetRelease(out var newRelease)) return _detectedBuffer;
|
if (!_detectedDoubleBuffer.TryGetRelease(out var newRelease)) return _detectedBuffer;
|
||||||
@@ -33,12 +34,13 @@ namespace BITKit.Sensors
|
|||||||
Profiler.EndSample();
|
Profiler.EndSample();
|
||||||
return _detectedBuffer;
|
return _detectedBuffer;
|
||||||
}
|
}
|
||||||
private readonly DoubleBuffer<IEnumerable<Transform>> _detectedDoubleBuffer=new();
|
|
||||||
private IEnumerable<Transform> _detectedBuffer;
|
|
||||||
|
|
||||||
|
private readonly DoubleBuffer<IEnumerable<Transform>> _detectedDoubleBuffer = new();
|
||||||
public override UniTask Execute()
|
private IEnumerable<Transform> _detectedBuffer=Array.Empty<Transform>();
|
||||||
|
|
||||||
|
public override UniTask Execute(float delta)
|
||||||
{
|
{
|
||||||
|
tempHashSet.Clear();
|
||||||
var length = Physics.OverlapSphereNonAlloc(Transform.position, radius, colliders, detectLayer);
|
var length = Physics.OverlapSphereNonAlloc(Transform.position, radius, colliders, detectLayer);
|
||||||
Profiler.BeginSample("Filter Detected Colliders");
|
Profiler.BeginSample("Filter Detected Colliders");
|
||||||
var _newDetected = from x in colliders.Take(length) where IsValid(x) select x.transform;
|
var _newDetected = from x in colliders.Take(length) where IsValid(x) select x.transform;
|
||||||
@@ -54,7 +56,7 @@ namespace BITKit.Sensors
|
|||||||
case var _ when ignoreColliders.Contains(_collider):
|
case var _ when ignoreColliders.Contains(_collider):
|
||||||
return false;
|
return false;
|
||||||
case var _ when fov > 0 && CheckFov(ref _collider) is false:
|
case var _ when fov > 0 && CheckFov(ref _collider) is false:
|
||||||
case var _ when requireSight && CheckSight(ref _collider) is false:
|
case var _ when requireSight && CheckSight(ref _collider) is false:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
@@ -62,18 +64,21 @@ namespace BITKit.Sensors
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override float GetDistance() => radius;
|
public override float GetDistance() => radius;
|
||||||
|
|
||||||
private bool CheckFov(ref Collider _collider)
|
private bool CheckFov(ref Collider _collider)
|
||||||
{
|
{
|
||||||
var _dir = _collider.transform.position - transform.position;
|
var _dir = _collider.bounds.center - transform.position;
|
||||||
if (_dir.sqrMagnitude <= 0) return false;
|
if (_dir.sqrMagnitude <= 0) return false;
|
||||||
var dir = Quaternion.LookRotation(_dir);
|
var dir = Quaternion.LookRotation(_dir);
|
||||||
return Vector3.Dot(transform.forward, _dir) > 0 && fov > Quaternion.Angle(transform.rotation, dir);
|
return Vector3.Dot(transform.forward, _dir) > 0 && fov > Quaternion.Angle(transform.rotation, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CheckSight(ref Collider _collider)
|
private bool CheckSight(ref Collider _collider)
|
||||||
{
|
{
|
||||||
if (!requireSight) return false;
|
if (!requireSight) return false;
|
||||||
var transform1 = _collider.transform;
|
var position = _collider.bounds.center;
|
||||||
var position = transform1.position;
|
//是检测bounds的顶部
|
||||||
|
position.y += _collider.bounds.extents.y;
|
||||||
var location = new Location(Transform);
|
var location = new Location(Transform);
|
||||||
var length = Physics.RaycastNonAlloc(
|
var length = Physics.RaycastNonAlloc(
|
||||||
location.position,
|
location.position,
|
||||||
@@ -82,23 +87,32 @@ namespace BITKit.Sensors
|
|||||||
Vector3.Distance(location, position),
|
Vector3.Distance(location, position),
|
||||||
blockLayer
|
blockLayer
|
||||||
);
|
);
|
||||||
|
|
||||||
switch (length)
|
switch (length)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
Debug.DrawLine(location, position, Color.green, 1);
|
||||||
return true;
|
return true;
|
||||||
case 1:
|
case 1:
|
||||||
if (hits[0].collider == _collider)
|
return hits[0].collider == _collider;
|
||||||
{
|
default:
|
||||||
return true;
|
var collider1 = _collider;
|
||||||
}
|
if (hits.Take(length).Any(Predicate))
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (hits.Take(length).Any(x => ignoreColliders.Contains(x.collider) is false))
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
bool Predicate(RaycastHit x)
|
||||||
|
{
|
||||||
|
var result = ignoreColliders.Contains(x.collider) is false && x.collider != collider1;
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
Debug.DrawLine(location, x.point, Color.red, 1);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,7 +13,7 @@ namespace BITKit.Sensors
|
|||||||
public float distance;
|
public float distance;
|
||||||
public override IEnumerable<Transform> Get() => detected;
|
public override IEnumerable<Transform> Get() => detected;
|
||||||
private readonly RaycastHit[] raycasts = new RaycastHit[16];
|
private readonly RaycastHit[] raycasts = new RaycastHit[16];
|
||||||
public override UniTask Execute()
|
public override UniTask Execute(float delta)
|
||||||
{
|
{
|
||||||
var _transform = transform;
|
var _transform = transform;
|
||||||
var forward = _transform.forward;
|
var forward = _transform.forward;
|
||||||
@@ -46,7 +46,7 @@ namespace BITKit.Sensors
|
|||||||
{
|
{
|
||||||
if (autoUpdate)
|
if (autoUpdate)
|
||||||
{
|
{
|
||||||
Execute().Forget();
|
Execute(Time.deltaTime).Forget();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
@@ -10,6 +11,7 @@ namespace BITKit.Sensors
|
|||||||
public class SensorQueue : MonoBehaviour
|
public class SensorQueue : MonoBehaviour
|
||||||
{
|
{
|
||||||
internal static readonly Dictionary<int,ISensor> Sensors=new();
|
internal static readonly Dictionary<int,ISensor> Sensors=new();
|
||||||
|
internal static readonly ConcurrentDictionary<int, float> LastDetectedTime = new();
|
||||||
private static bool IsDirty;
|
private static bool IsDirty;
|
||||||
|
|
||||||
[SerializeField,ReadOnly] private int _position;
|
[SerializeField,ReadOnly] private int _position;
|
||||||
@@ -32,10 +34,25 @@ namespace BITKit.Sensors
|
|||||||
}
|
}
|
||||||
|
|
||||||
[SerializeField] private MonoBehaviour[] sensors;
|
[SerializeField] private MonoBehaviour[] sensors;
|
||||||
|
[SerializeReference,SubclassSelector] private ITicker ticker;
|
||||||
private void Update()
|
|
||||||
|
private bool _isBusy;
|
||||||
|
|
||||||
|
private void Start()
|
||||||
{
|
{
|
||||||
|
ticker.Add(OnTick);
|
||||||
|
destroyCancellationToken.Register(Dispose);
|
||||||
|
}
|
||||||
|
private void Dispose()
|
||||||
|
{
|
||||||
|
ticker.Remove(OnTick);
|
||||||
|
}
|
||||||
|
private async void OnTick(float obj)
|
||||||
|
{
|
||||||
|
if (_isBusy) return;
|
||||||
if (SensorGlobalSettings.Enabled is false) return;
|
if (SensorGlobalSettings.Enabled is false) return;
|
||||||
|
|
||||||
|
_isBusy = true;
|
||||||
if(IsDirty)
|
if(IsDirty)
|
||||||
{
|
{
|
||||||
_position = 0;
|
_position = 0;
|
||||||
@@ -44,11 +61,25 @@ namespace BITKit.Sensors
|
|||||||
sensors = Sensors.Values.Where(IsEnabled).OfType<MonoBehaviour>().ToArray();
|
sensors = Sensors.Values.Where(IsEnabled).OfType<MonoBehaviour>().ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Sensors.Count is 0) return;
|
if (Sensors.Count is 0)
|
||||||
|
{
|
||||||
Sensors.ElementAt(_position++).Value.Execute().Forget();
|
_isBusy = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var current = Sensors.ElementAt(_position++).Value;
|
||||||
|
var currentUpdateTime = LastDetectedTime.GetOrAdd(current.Id,Time.time);
|
||||||
|
await current.Execute(Time.time-currentUpdateTime);
|
||||||
|
float UpdateValueFactory(int key, float old) => Time.time;
|
||||||
|
LastDetectedTime.AddOrUpdate(current.Id,Time.time,UpdateValueFactory);
|
||||||
|
|
||||||
|
if (destroyCancellationToken.IsCancellationRequested) {
|
||||||
|
_isBusy = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_position %= Sensors.Count;
|
_position %= Sensors.Count;
|
||||||
|
_isBusy = false;
|
||||||
}
|
}
|
||||||
private bool IsEnabled(ISensor sensor)
|
private bool IsEnabled(ISensor sensor)
|
||||||
{
|
{
|
||||||
@@ -60,4 +91,4 @@ namespace BITKit.Sensors
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -3,6 +3,8 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using BITKit.Sensors.States;
|
||||||
|
using BITKit.StateMachine;
|
||||||
using Cysharp.Threading.Tasks;
|
using Cysharp.Threading.Tasks;
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
@@ -16,212 +18,38 @@ using UnityEngine.UIElements;
|
|||||||
|
|
||||||
namespace BITKit.Sensors
|
namespace BITKit.Sensors
|
||||||
{
|
{
|
||||||
|
public interface ISmartTargetProperty{}
|
||||||
|
public interface ISmartTargetState:IState{}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 智能目标传感器,根据条件,智能选择目标
|
/// 智能目标传感器,根据条件,智能选择目标
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class SmartTargetSensor :MonoBehaviour,ISensor,IAction
|
public class SmartTargetSensor :StateBasedMonoBehaviour<ISmartTargetState>,ISensor
|
||||||
{
|
{
|
||||||
/// <summary>
|
[SerializeField] private float radius;
|
||||||
/// 自动更新
|
[SerializeField] private RangeSensor rangeSensor;
|
||||||
/// </summary>
|
[SerializeField] private AudioSensor audioSensor;
|
||||||
[Header(Constant.Header.Settings)]
|
public int Id { get; set; }
|
||||||
[SerializeField] private bool autoUpdate;
|
private readonly CacheList<Transform> _detected=new();
|
||||||
[SerializeField] private Optional<string[]> ignoreTags;
|
|
||||||
[SerializeField] private Optional<IntervalUpdate> optionalRetargetInterval;
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 主传感器
|
|
||||||
/// </summary>
|
|
||||||
[Header(nameof(Sensor))]
|
|
||||||
[SerializeField,SerializeReference,SubclassSelector] private ISensor sensor;
|
|
||||||
|
|
||||||
[Header(Constant.Header.Debug)]
|
|
||||||
[SerializeReference, ReadOnly] private int updateCount;
|
|
||||||
|
|
||||||
public IEnumerable<Transform> Get() =>CurrentTarget is not null ? new[] { CurrentTarget }:Enumerable.Empty<Transform>();
|
|
||||||
|
|
||||||
bool ISensor.AutoUpdate => autoUpdate;
|
|
||||||
|
|
||||||
internal StringBuilder reportBuilder;
|
|
||||||
internal DoubleBuffer<string> report=new();
|
|
||||||
|
|
||||||
public bool IsValid(Collider _collider)
|
|
||||||
{
|
|
||||||
if (!_collider) return false;
|
|
||||||
if (ignoreTags.Allow)
|
|
||||||
{
|
|
||||||
if (_collider.TryGetComponent<ITag>(out var iTags))
|
|
||||||
{
|
|
||||||
var tags = iTags.GetTags();
|
|
||||||
foreach (var x in ignoreTags.Value)
|
|
||||||
{
|
|
||||||
if (tags.Contains(x))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public float GetDistance() => sensor.GetDistance();
|
|
||||||
public Transform CurrentTarget { get; private set; }
|
|
||||||
private IEnumerable<Transform> detected = ArraySegment<Transform>.Empty;
|
|
||||||
private Vector3 _currentPosition;
|
|
||||||
private int Id;
|
|
||||||
|
|
||||||
private CancellationTokenSource timeoutCancellationTokenSource=new();
|
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
{
|
{
|
||||||
SensorQueue.Register(Id=GetInstanceID(),this);
|
Id = GetInstanceID();
|
||||||
|
SensorQueue.Register(Id,this);
|
||||||
|
}
|
||||||
|
private void Start()
|
||||||
|
{
|
||||||
|
TransitionState<Idle>();
|
||||||
}
|
}
|
||||||
private void OnDisable()
|
private void OnDisable()
|
||||||
{
|
{
|
||||||
SensorQueue.UnRegister(Id);
|
SensorQueue.UnRegister(Id);
|
||||||
}
|
}
|
||||||
public async UniTask Execute()
|
public IEnumerable<Transform> Get() => _detected.ValueArray;
|
||||||
|
public bool IsValid(Collider _collider) => false;
|
||||||
|
public float GetDistance() => radius;
|
||||||
|
public UniTask Execute(float delta)
|
||||||
{
|
{
|
||||||
try
|
CurrentState?.OnStateUpdate(delta);
|
||||||
{
|
return UniTask.CompletedTask;
|
||||||
_currentPosition = transform.position;
|
|
||||||
updateCount++;
|
|
||||||
timeoutCancellationTokenSource?.Cancel();
|
|
||||||
timeoutCancellationTokenSource = new CancellationTokenSource();
|
|
||||||
await sensor.Execute();
|
|
||||||
|
|
||||||
reportBuilder?.AppendLine($"-----BEGIN------{updateCount}");
|
|
||||||
|
|
||||||
Profiler.BeginSample("Release Detected Buffer");
|
|
||||||
var newDetected = sensor.Get();
|
|
||||||
|
|
||||||
if (reportBuilder is not null)
|
|
||||||
{
|
|
||||||
reportBuilder.AppendLine($"Detected:{newDetected.Count()}");
|
|
||||||
foreach (var x in newDetected)
|
|
||||||
{
|
|
||||||
reportBuilder.AppendLine(x.name);
|
|
||||||
}
|
|
||||||
reportBuilder.AppendLine();
|
|
||||||
}
|
|
||||||
Profiler.EndSample();
|
|
||||||
// ReSharper disable once PossibleMultipleEnumeration
|
|
||||||
if (newDetected.Contains(CurrentTarget))
|
|
||||||
{
|
|
||||||
if (optionalRetargetInterval.Allow && optionalRetargetInterval.Value.AllowUpdate)
|
|
||||||
{
|
|
||||||
reportBuilder?.AppendLine("Retarget Interval Catch,Search New Target");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
reportBuilder?.AppendLine("Current Target Detected,Keep Target");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Profiler.BeginSample("Filter Detected");
|
|
||||||
|
|
||||||
foreach (var x in newDetected.OrderBy(KeySelector))
|
|
||||||
{
|
|
||||||
if(IsValid(x.GetComponent<Collider>()) is false)continue;
|
|
||||||
CurrentTarget = x;
|
|
||||||
reportBuilder?.AppendLine($"New Target:{x.name},Is oder by distance");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
Profiler.EndSample();
|
|
||||||
|
|
||||||
reportBuilder?.AppendLine($"-----Complete------{updateCount}");
|
|
||||||
|
|
||||||
if(reportBuilder is not null)
|
|
||||||
{
|
|
||||||
report.Release(reportBuilder.ToString());
|
|
||||||
reportBuilder.Clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
report.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
BIT4Log.LogException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
private float KeySelector(Transform x)
|
|
||||||
{
|
|
||||||
var distance = Vector3.Distance(_currentPosition, x.position);
|
|
||||||
reportBuilder?.AppendLine($"Distance:{distance}@{x.name}");
|
|
||||||
return distance;
|
|
||||||
}
|
|
||||||
void IAction.Execute()
|
|
||||||
{
|
|
||||||
Execute().Forget();
|
|
||||||
}
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
private void OnDrawGizmosSelected()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!CurrentTarget) return;
|
|
||||||
Gizmos.DrawLine(transform.position,CurrentTarget.position);
|
|
||||||
}
|
|
||||||
catch (UnassignedReferenceException)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#if UNITY_EDITOR
|
|
||||||
[CustomEditor(typeof(SmartTargetSensor))]
|
|
||||||
public class SmartTargetSensorInspector:BITInspector<SmartTargetSensor>
|
|
||||||
{
|
|
||||||
private ObjectField _objectField;
|
|
||||||
private Label _reportLabel;
|
|
||||||
public override VisualElement CreateInspectorGUI()
|
|
||||||
{
|
|
||||||
FillDefaultInspector();
|
|
||||||
|
|
||||||
CreateSubTitle("Editor Debug Field");
|
|
||||||
|
|
||||||
_objectField = root.Create<ObjectField>();
|
|
||||||
|
|
||||||
_objectField.objectType = typeof(Transform);
|
|
||||||
|
|
||||||
_objectField.SetEnabled(false);
|
|
||||||
|
|
||||||
_reportLabel = root.Create<Label>();
|
|
||||||
|
|
||||||
_reportLabel.text = "Waiting agent report";
|
|
||||||
|
|
||||||
return root;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnEnabled()
|
|
||||||
{
|
|
||||||
base.OnEnabled();
|
|
||||||
agent.reportBuilder = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDisabled()
|
|
||||||
{
|
|
||||||
base.OnDisabled();
|
|
||||||
agent.reportBuilder = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnUpdate()
|
|
||||||
{
|
|
||||||
if (_objectField is not null)
|
|
||||||
{
|
|
||||||
_objectField.value = agent.CurrentTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (agent.reportBuilder is not null && _reportLabel is not null && agent.report.TryGetRelease(out var value))
|
|
||||||
{
|
|
||||||
_reportLabel.text = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
30
Src/Unity/Scripts/Sensor/Smart/SmartTargetSensorStates.cs
Normal file
30
Src/Unity/Scripts/Sensor/Smart/SmartTargetSensorStates.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using BITKit.StateMachine;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace BITKit.Sensors.States
|
||||||
|
{
|
||||||
|
public abstract class SmartTargetSensorStates : ISmartTargetState
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
public virtual void Initialize()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public virtual void OnStateEntry(IState old)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public virtual void OnStateUpdate(float deltaTime)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
public virtual void OnStateExit(IState old, IState newState)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[Serializable]
|
||||||
|
public sealed class Idle : SmartTargetSensorStates
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d55e592432e5ca648b8b9eddee224932
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@@ -61,6 +61,8 @@ namespace BITKit.Sensors
|
|||||||
onLost.Invoke(_collider);
|
onLost.Invoke(_collider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public int Id => _id is 0 ? _id = GetInstanceID() : _id;
|
||||||
|
private int _id;
|
||||||
|
|
||||||
public IEnumerable<Transform> Get()
|
public IEnumerable<Transform> Get()
|
||||||
{
|
{
|
||||||
@@ -89,13 +91,11 @@ namespace BITKit.Sensors
|
|||||||
if (ignores.Contains(detectedObject)) return false;
|
if (ignores.Contains(detectedObject)) return false;
|
||||||
return !detectedLayer.Allow || detectedLayer.Value.Includes(_collider.gameObject.layer);
|
return !detectedLayer.Allow || detectedLayer.Value.Includes(_collider.gameObject.layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float GetDistance()
|
public float GetDistance()
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
public UniTask Execute(float delta = 0)=>
|
||||||
public UniTask Execute()=>
|
|
||||||
UniTask.CompletedTask;
|
UniTask.CompletedTask;
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
|
@@ -13,7 +13,8 @@ namespace BITKit
|
|||||||
[SerializeField] private string[] tags;
|
[SerializeField] private string[] tags;
|
||||||
[Tooltip("Disable when tags is not empty")]
|
[Tooltip("Disable when tags is not empty")]
|
||||||
[SerializeReference,SubclassSelector] private IReference[] reference;
|
[SerializeReference,SubclassSelector] private IReference[] reference;
|
||||||
|
public int Hash => _id is 0 ? _id = MathE.GetHash(GetTags()) : _id;
|
||||||
|
private int _id;
|
||||||
public string[] GetTags() => CacheTags ??= reference?.Length > 0 ? reference.Select(x => x.Value).ToArray() : tags;
|
public string[] GetTags() => CacheTags ??= reference?.Length > 0 ? reference.Select(x => x.Value).ToArray() : tags;
|
||||||
private string[] CacheTags;
|
private string[] CacheTags;
|
||||||
public void SetTags(IReference[] newReference)
|
public void SetTags(IReference[] newReference)
|
||||||
|
@@ -55,7 +55,7 @@ namespace BITKit
|
|||||||
{
|
{
|
||||||
await UniTask.SwitchToMainThread();
|
await UniTask.SwitchToMainThread();
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
if (EditorApplication.isPlaying is false)
|
if (EditorApplication.isPlaying is false || EditorApplication.isPaused)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
8
Src/Unity/Scripts/UX/Chart.meta
Normal file
8
Src/Unity/Scripts/UX/Chart.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 67732f32069d3bb4ca436ef8de5710e2
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
24
Src/Unity/Scripts/UX/Chart/BITKit.UX.Chart.Runtime.asmdef
Normal file
24
Src/Unity/Scripts/UX/Chart/BITKit.UX.Chart.Runtime.asmdef
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
{
|
||||||
|
"name": "BITKit.UX.Chart.Runtime",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [
|
||||||
|
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||||
|
"GUID:6ef4ed8ff60a7aa4bb60a8030e6f4008",
|
||||||
|
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||||
|
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||||
|
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||||
|
"GUID:6de01b04fa4e14662b03fa46366da151",
|
||||||
|
"GUID:f19bbd83e3c264a5680926bf75d7e494"
|
||||||
|
],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [
|
||||||
|
"_SkiaSharp"
|
||||||
|
],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 994a3fb33a5627740b0712e7c483cc1f
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
202
Src/Unity/Scripts/UX/Chart/SkiaChart.cs
Normal file
202
Src/Unity/Scripts/UX/Chart/SkiaChart.cs
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using SkiaSharp;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
|
||||||
|
namespace BITKit.UX
|
||||||
|
{
|
||||||
|
public class SkiaChart : VisualElement
|
||||||
|
{
|
||||||
|
public new class UxmlTraits : VisualElement.UxmlTraits
|
||||||
|
{
|
||||||
|
private readonly UxmlStringAttributeDescription m_JsonAttribute = new ()
|
||||||
|
{
|
||||||
|
name = "Json"
|
||||||
|
};
|
||||||
|
private readonly UxmlBoolAttributeDescription m_allowWarningsAttribute = new ()
|
||||||
|
{
|
||||||
|
name = "allowWarnings",
|
||||||
|
defaultValue = false
|
||||||
|
};
|
||||||
|
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
|
||||||
|
{
|
||||||
|
base.Init(ve, bag, cc);
|
||||||
|
var x = (SkiaChart)ve;
|
||||||
|
x.Json = m_JsonAttribute.GetValueFromBag(bag, cc);
|
||||||
|
x.AllowWarning = m_allowWarningsAttribute.GetValueFromBag(bag, cc);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public new class UxmlFactory : UxmlFactory<SkiaChart, UxmlTraits> { }
|
||||||
|
public SkiaChart()
|
||||||
|
{
|
||||||
|
RegisterCallback<GeometryChangedEvent>(x =>
|
||||||
|
{
|
||||||
|
if (visible)
|
||||||
|
{
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}); RegisterCallback<CustomStyleResolvedEvent>(OnCustomStyleResolved);
|
||||||
|
|
||||||
|
style.flexDirection = FlexDirection.Row;
|
||||||
|
_dataContainer = this.Create<VisualElement>();
|
||||||
|
_chartContainer = this.Create<VisualElement>();
|
||||||
|
_chartContainer.style.flexGrow = 1;
|
||||||
|
|
||||||
|
_dataContainer.style.justifyContent = Justify.SpaceBetween;
|
||||||
|
|
||||||
|
_dataContainer.name = "Data";
|
||||||
|
_chartContainer.name = "Chart";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCustomStyleResolved(CustomStyleResolvedEvent evt)
|
||||||
|
{
|
||||||
|
if(evt.customStyle.TryGetValue(new CustomStyleProperty<Color>("--chart-secondary-color"), out var helpLineColor))
|
||||||
|
{
|
||||||
|
_secondaryColor = helpLineColor;
|
||||||
|
}
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Json
|
||||||
|
{
|
||||||
|
get => _json;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_json = value;
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private string _json;
|
||||||
|
public bool AllowWarning { get; set; }
|
||||||
|
public Color SecondaryColor
|
||||||
|
{
|
||||||
|
get => _secondaryColor;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_secondaryColor = value;
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private Color _secondaryColor;
|
||||||
|
|
||||||
|
private readonly VisualElement _dataContainer;
|
||||||
|
private readonly VisualElement _chartContainer;
|
||||||
|
private void Rebuild()
|
||||||
|
{
|
||||||
|
var data = Array.Empty<float>();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
data = JsonConvert.DeserializeObject<float[]>(Json);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (AllowWarning)
|
||||||
|
Debug.LogException(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(float.IsNaN(layout.width) || float.IsNaN(layout.height))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (data is null or { Length: 0 }) return;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_dataContainer.Clear();
|
||||||
|
_chartContainer.Clear();
|
||||||
|
|
||||||
|
var max = data.Max();
|
||||||
|
var min = data.Min();
|
||||||
|
//假如min是x,max是y,将中间的差用data.Length划分
|
||||||
|
|
||||||
|
_dataContainer.style.flexDirection = FlexDirection.ColumnReverse;
|
||||||
|
for (var i = 0; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
var label = _dataContainer.Create<Label>();
|
||||||
|
|
||||||
|
var value = (max - min) / (data.Length - 1) * i + min;
|
||||||
|
label.text = value.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if(_chartContainer.layout.width is float.NaN or <10 || _chartContainer.layout.height is float.NaN or <10)
|
||||||
|
return;
|
||||||
|
var info = new SKImageInfo(
|
||||||
|
width: (int)_chartContainer.layout.width,
|
||||||
|
height: (int)_chartContainer.layout.height,
|
||||||
|
colorType: SKColorType.Rgba8888,
|
||||||
|
alphaType: SKAlphaType.Premul
|
||||||
|
);
|
||||||
|
|
||||||
|
using var surface = SKSurface.Create(info);
|
||||||
|
|
||||||
|
using var canvas = surface.Canvas;
|
||||||
|
|
||||||
|
using var linePaint = new SKPaint();
|
||||||
|
linePaint.Color = resolvedStyle.color.ToSKColor();
|
||||||
|
linePaint.StrokeWidth = resolvedStyle.unityTextOutlineWidth;
|
||||||
|
linePaint.IsAntialias = true;
|
||||||
|
linePaint.Style = SKPaintStyle.Stroke;
|
||||||
|
|
||||||
|
using var helpLinePaint = new SKPaint();
|
||||||
|
helpLinePaint.Color = resolvedStyle.unityTextOutlineColor.ToSKColor();
|
||||||
|
helpLinePaint.StrokeWidth = 1;
|
||||||
|
helpLinePaint.Style = SKPaintStyle.Stroke;
|
||||||
|
|
||||||
|
using var fillPaint = new SKPaint();
|
||||||
|
fillPaint.Color = new SKColor(200, 200, 200, 200);
|
||||||
|
fillPaint.Style=SKPaintStyle.Fill;
|
||||||
|
|
||||||
|
DoubleBuffer<SKPoint> buffer = new();
|
||||||
|
|
||||||
|
var path = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||||
|
|
||||||
|
path.MoveTo(0,0);
|
||||||
|
path.LineTo(0,0);
|
||||||
|
|
||||||
|
for (var i = 0; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
var value = data[i];
|
||||||
|
var posX = (float)info.Width / (data.Length - 1) * (i);
|
||||||
|
var d = max - min;
|
||||||
|
var p = (value - min) / d;
|
||||||
|
var poxY = info.Height * p;
|
||||||
|
|
||||||
|
var currentPoint = new SKPoint(posX, poxY);
|
||||||
|
if (buffer.TryGetRelease(out var previousPoint))
|
||||||
|
{
|
||||||
|
canvas.DrawLine(previousPoint, currentPoint, linePaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
var label = _chartContainer.Create<Label>();
|
||||||
|
label.text = value.ToString(CultureInfo.InvariantCulture);
|
||||||
|
label.style.position = Position.Absolute;
|
||||||
|
label.style.left = posX;//-label.layout.width/2;
|
||||||
|
label.style.bottom = poxY;//- label.layout.height/2;
|
||||||
|
|
||||||
|
canvas.DrawLine(posX, 0, posX, poxY, helpLinePaint);
|
||||||
|
|
||||||
|
path.LineTo(posX,poxY);
|
||||||
|
|
||||||
|
buffer.Release(currentPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
path.LineTo(info.Width,0);
|
||||||
|
path.Close();
|
||||||
|
|
||||||
|
|
||||||
|
//canvas.DrawPath(path,filePaint);
|
||||||
|
|
||||||
|
var texture = info.ToTexture2D(surface);
|
||||||
|
|
||||||
|
_chartContainer.style.backgroundImage = texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Src/Unity/Scripts/UX/Chart/SkiaChart.cs.meta
Normal file
11
Src/Unity/Scripts/UX/Chart/SkiaChart.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 00511c331928b714d919870827a5c326
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
35
Src/Unity/Scripts/UX/Chart/SkiaExtensions.cs
Normal file
35
Src/Unity/Scripts/UX/Chart/SkiaExtensions.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using SkiaSharp;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace BITKit.UX
|
||||||
|
{
|
||||||
|
public static class SkiaExtensions
|
||||||
|
{
|
||||||
|
public static Texture2D ToTexture2D(this SKImageInfo info,SKSurface surface)
|
||||||
|
{
|
||||||
|
// Okay, we're finished drawing. Now we create a Unity texture.
|
||||||
|
TextureFormat format = (info.ColorType == SKColorType.Rgba8888) ? TextureFormat.RGBA32 : TextureFormat.BGRA32;
|
||||||
|
var texture = new Texture2D(info.Width, info.Height, format, false, true);
|
||||||
|
texture.wrapMode = TextureWrapMode.Clamp;
|
||||||
|
|
||||||
|
// Pull a Skia image object out of the canvas...
|
||||||
|
var pixmap = surface.PeekPixels();
|
||||||
|
// Copy it to the Unity texture...
|
||||||
|
texture.LoadRawTextureData(pixmap.GetPixels(), pixmap.RowBytes * pixmap.Height);
|
||||||
|
texture.Apply(false, true);
|
||||||
|
// And drop it into the RawImage object.
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
public static SKColor ToSKColor(this Color color,byte? alpha=null)
|
||||||
|
{
|
||||||
|
return new SKColor((byte)(color.r * 255), (byte)(color.g * 255), (byte)(color.b * 255), alpha??(byte)(color.a * 255));
|
||||||
|
}
|
||||||
|
public static SKColor ToSKColor(this Color32 color)
|
||||||
|
{
|
||||||
|
return new SKColor(color.r, color.g, color.b, color.a);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Src/Unity/Scripts/UX/Chart/SkiaExtensions.cs.meta
Normal file
11
Src/Unity/Scripts/UX/Chart/SkiaExtensions.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c23b988a0ca3904468edef1bd026f977
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
8
Src/Unity/Scripts/UX/Chart/Test.meta
Normal file
8
Src/Unity/Scripts/UX/Chart/Test.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 614549820bd3c514eaf369e4895d1ef0
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
25
Src/Unity/Scripts/UX/Chart/Test/BITKit.UX.Chart.Tests.asmdef
Normal file
25
Src/Unity/Scripts/UX/Chart/Test/BITKit.UX.Chart.Tests.asmdef
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"name": "BITKit.UX.Chart.Tests",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [
|
||||||
|
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||||
|
"GUID:6ef4ed8ff60a7aa4bb60a8030e6f4008",
|
||||||
|
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||||
|
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||||
|
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||||
|
"GUID:6de01b04fa4e14662b03fa46366da151",
|
||||||
|
"GUID:f19bbd83e3c264a5680926bf75d7e494",
|
||||||
|
"GUID:994a3fb33a5627740b0712e7c483cc1f"
|
||||||
|
],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [
|
||||||
|
"_SkiaSharp"
|
||||||
|
],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
@@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 8acc186ca11c9df42b8ab94c1e952e73
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
99
Src/Unity/Scripts/UX/Chart/Test/SKPaintComponent.cs
Normal file
99
Src/Unity/Scripts/UX/Chart/Test/SKPaintComponent.cs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Linq;
|
||||||
|
using SkiaSharp;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace BITKit.UX
|
||||||
|
{
|
||||||
|
public class SKPaintComponent : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private Texture2D texture;
|
||||||
|
[SerializeField] private float[] data;
|
||||||
|
|
||||||
|
[BIT]
|
||||||
|
private void Draw()
|
||||||
|
{
|
||||||
|
var info = new SKImageInfo(
|
||||||
|
width: 384,
|
||||||
|
height: 128,
|
||||||
|
colorType: SKColorType.Rgba8888,
|
||||||
|
alphaType: SKAlphaType.Premul
|
||||||
|
);
|
||||||
|
|
||||||
|
using var surface = SKSurface.Create(info);
|
||||||
|
|
||||||
|
|
||||||
|
using var canvas = surface.Canvas;
|
||||||
|
|
||||||
|
//canvas.Clear(new Color32(31,31,31,255).ToSKColor());
|
||||||
|
|
||||||
|
using var linePaint = new SKPaint();
|
||||||
|
linePaint.Color = new SKColor(255, 0, 0, 255);
|
||||||
|
linePaint.StrokeWidth = 8;
|
||||||
|
linePaint.IsAntialias = true;
|
||||||
|
linePaint.Style = SKPaintStyle.Stroke;
|
||||||
|
|
||||||
|
using var helpLinePaint = new SKPaint();
|
||||||
|
helpLinePaint.Color = new SKColor(200, 200, 200, 200);
|
||||||
|
helpLinePaint.StrokeWidth = 4;
|
||||||
|
helpLinePaint.Style = SKPaintStyle.Stroke;
|
||||||
|
|
||||||
|
using var textPaint = new SKPaint();
|
||||||
|
textPaint.TextAlign = SKTextAlign.Center;
|
||||||
|
textPaint.TextSize = 14;
|
||||||
|
textPaint.ColorF = new SKColor(0, 255, 0, 255);
|
||||||
|
|
||||||
|
using var filePaint = new SKPaint();
|
||||||
|
filePaint.Color = new SKColor(200, 200, 200, 200);
|
||||||
|
filePaint.Style=SKPaintStyle.Fill;
|
||||||
|
|
||||||
|
var min = data.Min();
|
||||||
|
var max = data.Max();
|
||||||
|
|
||||||
|
DoubleBuffer<SKPoint> buffer = new();
|
||||||
|
|
||||||
|
var path = new SKPath { FillType = SKPathFillType.EvenOdd };
|
||||||
|
|
||||||
|
path.MoveTo(0,0);
|
||||||
|
path.LineTo(0,0);
|
||||||
|
|
||||||
|
for (var i = 0; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
var value = data[i];
|
||||||
|
var posX = (float)info.Width / (data.Length - 1) * (i);
|
||||||
|
var d = max - min;
|
||||||
|
var p = (value - min) / d;
|
||||||
|
var poxY = info.Height * p;
|
||||||
|
|
||||||
|
var currentPoint = new SKPoint(posX, poxY);
|
||||||
|
if (buffer.TryGetRelease(out var previousPoint))
|
||||||
|
{
|
||||||
|
canvas.DrawLine(previousPoint, currentPoint, linePaint);
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas.DrawText(
|
||||||
|
value.ToString()
|
||||||
|
, currentPoint
|
||||||
|
, new SKFont(
|
||||||
|
SKTypeface.FromFile(@"D:\Iris\Documents\GitHub\iFactory-YL106.Unity\Assets\BITKit\Unity\Art\Fonts\TTF\Roboto\Roboto-Regular.ttf")
|
||||||
|
), textPaint);
|
||||||
|
canvas.DrawLine(posX, 0, posX, poxY, helpLinePaint);
|
||||||
|
|
||||||
|
path.LineTo(posX,poxY);
|
||||||
|
|
||||||
|
buffer.Release(currentPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
path.LineTo(info.Width,0);
|
||||||
|
path.Close();
|
||||||
|
|
||||||
|
|
||||||
|
//canvas.DrawPath(path,filePaint);
|
||||||
|
|
||||||
|
texture = info.ToTexture2D(surface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
11
Src/Unity/Scripts/UX/Chart/Test/SKPaintComponent.cs.meta
Normal file
11
Src/Unity/Scripts/UX/Chart/Test/SKPaintComponent.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4ce3dedf1c2068047a00040de957cb33
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@@ -30,7 +30,7 @@ namespace BITKit.UX
|
|||||||
container = this.visualElement.Q(UXConstant.ContextContainer);
|
container = this.visualElement.Q(UXConstant.ContextContainer);
|
||||||
toggle = this.visualElement.Q<Toggle>(UXConstant.Toggle);
|
toggle = this.visualElement.Q<Toggle>(UXConstant.Toggle);
|
||||||
}
|
}
|
||||||
public T Get<T>(int index) where T : VisualElement => visualElement.Q<T>($"{typeof(T).Name}--{index}");
|
public T Get<T>(int index = 0) where T : VisualElement => visualElement.Q<T>($"{typeof(T).Name}--{index}");
|
||||||
public void SetProcess(float process)
|
public void SetProcess(float process)
|
||||||
{
|
{
|
||||||
var radialProgress = visualElement.Q<RadialProgress>();
|
var radialProgress = visualElement.Q<RadialProgress>();
|
||||||
|
@@ -69,7 +69,7 @@ namespace BITKit.IData
|
|||||||
if(attribute != null)
|
if(attribute != null)
|
||||||
{
|
{
|
||||||
Name = attribute.Name;
|
Name = attribute.Name;
|
||||||
VisualElement.GetType().GetProperty("label",ReflectionHelper.Flags)!.SetValue(VisualElement, Name);
|
VisualElement.GetType().GetProperty("label",ReflectionHelper.Flags)?.SetValue(VisualElement, Name);
|
||||||
}
|
}
|
||||||
if (fieldInfo.GetCustomAttribute<ReadOnlyAttribute>() is not null)
|
if (fieldInfo.GetCustomAttribute<ReadOnlyAttribute>() is not null)
|
||||||
{
|
{
|
||||||
@@ -111,11 +111,22 @@ namespace BITKit.IData
|
|||||||
}
|
}
|
||||||
public sealed class UXStringBinder:UXDataBinder<string>
|
public sealed class UXStringBinder:UXDataBinder<string>
|
||||||
{
|
{
|
||||||
protected override VisualElement OnCreateUI() => new TextField()
|
protected override VisualElement OnCreateUI()
|
||||||
{
|
{
|
||||||
isDelayed = true,
|
if (this.fieldInfo.GetCustomAttribute<ReadOnlyAttribute>() is not null)
|
||||||
multiline = true
|
{
|
||||||
};
|
return new Label();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new TextField()
|
||||||
|
{
|
||||||
|
isDelayed = true,
|
||||||
|
multiline = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public sealed class UXFloat3Binder:UXDataBinder<float3>
|
public sealed class UXFloat3Binder:UXDataBinder<float3>
|
||||||
{
|
{
|
||||||
|
84
Src/Unity/Scripts/UX/Library/ProgressBlock.cs
Normal file
84
Src/Unity/Scripts/UX/Library/ProgressBlock.cs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UIElements;
|
||||||
|
|
||||||
|
namespace BITKit.UX
|
||||||
|
{
|
||||||
|
public class ProgressBlock : VisualElement
|
||||||
|
{
|
||||||
|
public new class UxmlTraits : VisualElement.UxmlTraits
|
||||||
|
{
|
||||||
|
private readonly UxmlIntAttributeDescription m_ValueAttribute = new ()
|
||||||
|
{
|
||||||
|
name = "Value",defaultValue = 50
|
||||||
|
};
|
||||||
|
private readonly UxmlIntAttributeDescription m_SeparateAttribute = new ()
|
||||||
|
{
|
||||||
|
name = "Separate",defaultValue = 5
|
||||||
|
};
|
||||||
|
|
||||||
|
public override void Init(VisualElement ve, IUxmlAttributes bag, CreationContext cc)
|
||||||
|
{
|
||||||
|
base.Init(ve, bag, cc);
|
||||||
|
var x = (ProgressBlock)ve;
|
||||||
|
x.Value = m_ValueAttribute.GetValueFromBag(bag, cc);
|
||||||
|
x.Separate = m_SeparateAttribute.GetValueFromBag(bag, cc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public ProgressBlock() : base()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public new class UxmlFactory : UxmlFactory<ProgressBlock, UxmlTraits> { }
|
||||||
|
/// <summary>
|
||||||
|
/// 值,默认50,范围0-100
|
||||||
|
/// </summary>
|
||||||
|
public int Value
|
||||||
|
{
|
||||||
|
get => value;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private int value;
|
||||||
|
/// <summary>
|
||||||
|
/// 分割线,默认5
|
||||||
|
/// </summary>
|
||||||
|
public int Separate
|
||||||
|
{
|
||||||
|
get => separate;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.separate = value;
|
||||||
|
Rebuild();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private int separate;
|
||||||
|
private void Rebuild()
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
//if value is 58
|
||||||
|
for (var i = 1; i <= Separate; i++)
|
||||||
|
{
|
||||||
|
var block = this.Create<VisualElement>();
|
||||||
|
block.style.flexGrow = 1;
|
||||||
|
|
||||||
|
if (i * 10 < Value)
|
||||||
|
{
|
||||||
|
block.style.opacity = 1;
|
||||||
|
}else if ((i + 1) * 10 > value)
|
||||||
|
{
|
||||||
|
block.style.opacity = 0.5f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
block.style.opacity = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
11
Src/Unity/Scripts/UX/Library/ProgressBlock.cs.meta
Normal file
11
Src/Unity/Scripts/UX/Library/ProgressBlock.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ca822b68d3588fd48abf69d987af2607
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@@ -51,7 +51,12 @@ namespace BITKit.UX
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
var bindPathAtt = fieldInfo.GetCustomAttribute<UXBindPathAttribute>();
|
var bindPathAtt = fieldInfo.GetCustomAttribute<UXBindPathAttribute>();
|
||||||
var ve = document.rootVisualElement.Q(bindPathAtt.Path);
|
VisualElement ve = document.rootVisualElement;
|
||||||
|
foreach (var path in bindPathAtt.Path.Split("."))
|
||||||
|
{
|
||||||
|
ve = ve.Q(path);
|
||||||
|
}
|
||||||
|
//ve = document.rootVisualElement.Q(bindPathAtt.Path);
|
||||||
if(bindPathAtt.CanBeNull is false && ve is null)
|
if(bindPathAtt.CanBeNull is false && ve is null)
|
||||||
BIT4Log.LogException(new NullReferenceException($"未找到{bindPathAtt.Path}"));
|
BIT4Log.LogException(new NullReferenceException($"未找到{bindPathAtt.Path}"));
|
||||||
fieldInfo.SetValue(self,ve);
|
fieldInfo.SetValue(self,ve);
|
||||||
|
@@ -41,7 +41,7 @@ namespace BITKit
|
|||||||
{
|
{
|
||||||
var obj = self.serializedObject.targetObject;
|
var obj = self.serializedObject.targetObject;
|
||||||
var type = obj.GetType();
|
var type = obj.GetType();
|
||||||
var field = type.GetField(self.propertyPath, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
|
var field = type.GetField(self.propertyPath, ReflectionHelper.Flags);
|
||||||
if (field is null)
|
if (field is null)
|
||||||
{
|
{
|
||||||
throw new NullReferenceException($"Field {self.propertyPath} is null");
|
throw new NullReferenceException($"Field {self.propertyPath} is null");
|
||||||
@@ -51,7 +51,6 @@ namespace BITKit
|
|||||||
public static void FillDefaultInspector(VisualElement container, SerializedObject serializedObject, bool hideScript)
|
public static void FillDefaultInspector(VisualElement container, SerializedObject serializedObject, bool hideScript)
|
||||||
{
|
{
|
||||||
container.Clear();
|
container.Clear();
|
||||||
|
|
||||||
if (serializedObject.targetObject is null)
|
if (serializedObject.targetObject is null)
|
||||||
{
|
{
|
||||||
var label = container.Create<Label>();
|
var label = container.Create<Label>();
|
||||||
@@ -70,7 +69,7 @@ namespace BITKit
|
|||||||
|
|
||||||
var type = serializedObject.targetObject.GetType();
|
var type = serializedObject.targetObject.GetType();
|
||||||
var fieldInfo = serializedObject.targetObject.GetType().GetField(property.propertyPath, ReflectionHelper.Flags);
|
var fieldInfo = serializedObject.targetObject.GetType().GetField(property.propertyPath, ReflectionHelper.Flags);
|
||||||
if (fieldInfo is not null && Attribute.IsDefined(fieldInfo, typeof(ReadOnlyAttribute),true))
|
if (fieldInfo is not null && type == typeof(string) && Attribute.IsDefined(fieldInfo, typeof(ReadOnlyAttribute),true))
|
||||||
{
|
{
|
||||||
var attribute = fieldInfo.GetCustomAttribute<ReadOnlyAttribute>();
|
var attribute = fieldInfo.GetCustomAttribute<ReadOnlyAttribute>();
|
||||||
var _container = container.Create<VisualElement>();
|
var _container = container.Create<VisualElement>();
|
||||||
@@ -92,16 +91,60 @@ namespace BITKit
|
|||||||
{
|
{
|
||||||
//var label = container.Create<Label>();
|
//var label = container.Create<Label>();
|
||||||
//label.text =$"propertyPath:{property.propertyPath} fieldInfo:{fieldInfo} type:{type} fieldInfo:{fieldInfo}";
|
//label.text =$"propertyPath:{property.propertyPath} fieldInfo:{fieldInfo} type:{type} fieldInfo:{fieldInfo}";
|
||||||
|
var _container = container;
|
||||||
|
|
||||||
var field = new PropertyField(property)
|
var field = new PropertyField(property)
|
||||||
{
|
{
|
||||||
name = "PropertyField:" + property.propertyPath
|
name = "PropertyField:" + property.propertyPath
|
||||||
};
|
};
|
||||||
|
if (fieldInfo is not null && Attribute.IsDefined(fieldInfo, typeof(ReadOnlyAttribute), true))
|
||||||
|
{
|
||||||
|
field.SetEnabled(false);
|
||||||
|
field.style.opacity = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (property.propertyPath == "m_Script" && serializedObject.targetObject != null)
|
if (property.propertyPath == "m_Script" && serializedObject.targetObject != null)
|
||||||
{
|
{
|
||||||
field.SetEnabled(false);
|
field.SetEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (fieldInfo?.FieldType == typeof(Texture2D) && fieldInfo.GetValue(serializedObject) is Texture2D texture && texture)
|
||||||
|
// {
|
||||||
|
// _container = container.Create<VisualElement>();
|
||||||
|
//
|
||||||
|
// var foldout = _container.Create<Foldout>();
|
||||||
|
// foldout.text = property.displayName;
|
||||||
|
//
|
||||||
|
// var icon = foldout.Create<VisualElement>();
|
||||||
|
// var slider = foldout.Create<Slider>();
|
||||||
|
//
|
||||||
|
// var width = 128;
|
||||||
|
// var m = texture.height /width;
|
||||||
|
//
|
||||||
|
// icon.style.width = width;
|
||||||
|
// icon.style.height = width*m;
|
||||||
|
// icon.style.backgroundImage = texture;
|
||||||
|
//
|
||||||
|
// field.style.flexGrow = 1;
|
||||||
|
//
|
||||||
|
// _container.style.backgroundColor =new StyleColor(new Color32(31,31,31,255)) ;
|
||||||
|
// _container.style.borderBottomLeftRadius = 5;
|
||||||
|
// _container.style.borderBottomRightRadius = 5;
|
||||||
|
// _container.style.borderTopLeftRadius = 5;
|
||||||
|
// _container.style.borderTopRightRadius = 5;
|
||||||
|
//
|
||||||
|
// slider.label = "Scale";
|
||||||
|
// slider.lowValue = 1;
|
||||||
|
// slider.highValue = 2;
|
||||||
|
// slider.RegisterValueChangedCallback(x =>
|
||||||
|
// {
|
||||||
|
// icon.style.width = width * x.newValue;
|
||||||
|
// icon.style.height = width*m * x.newValue;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
container.Add(field);
|
_container.Add(field);
|
||||||
}
|
}
|
||||||
// try
|
// try
|
||||||
// {
|
// {
|
||||||
@@ -123,7 +166,10 @@ namespace BITKit
|
|||||||
{
|
{
|
||||||
if (method.GetCustomAttribute<BITAttribute>() is null) continue;
|
if (method.GetCustomAttribute<BITAttribute>() is null) continue;
|
||||||
if (method.GetParameters().Length is not 0) continue;
|
if (method.GetParameters().Length is not 0) continue;
|
||||||
var button = new Button(() => method.Invoke(serializedObject.targetObject, null))
|
var button = new Button(() =>
|
||||||
|
{
|
||||||
|
method.Invoke(serializedObject.targetObject, null);
|
||||||
|
})
|
||||||
{
|
{
|
||||||
text = method.Name
|
text = method.Name
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -20,11 +21,13 @@ namespace BITKit
|
|||||||
private static VFXService sinleton;
|
private static VFXService sinleton;
|
||||||
public VFX[] vfxs;
|
public VFX[] vfxs;
|
||||||
private readonly Dictionary<string, UnityPool<Transform>> pools = new();
|
private readonly Dictionary<string, UnityPool<Transform>> pools = new();
|
||||||
|
private readonly ConcurrentDictionary<int, Transform> cache = new();
|
||||||
|
|
||||||
[SerializeField] private bool debug;
|
[SerializeField] private bool debug;
|
||||||
[SerializeField] private Optional<int> defaultCapacity;
|
[SerializeField] private Optional<int> defaultCapacity;
|
||||||
private void Awake()
|
private void Awake()
|
||||||
{
|
{
|
||||||
|
cache.Clear();
|
||||||
sinleton = this;
|
sinleton = this;
|
||||||
DI.Register(this);
|
DI.Register(this);
|
||||||
}
|
}
|
||||||
@@ -68,16 +71,22 @@ namespace BITKit
|
|||||||
|
|
||||||
public bool TryMatch(out Transform value, params string[] key)
|
public bool TryMatch(out Transform value, params string[] key)
|
||||||
{
|
{
|
||||||
foreach (var vfx in vfxs)
|
value=cache.GetOrAdd(MathE.GetHash(key),Add);
|
||||||
|
return value is not null;
|
||||||
|
Transform Add(int arg)
|
||||||
{
|
{
|
||||||
if (vfx.IsMatch(key))
|
foreach (var vfx in vfxs)
|
||||||
{
|
{
|
||||||
value = vfx.prefab;
|
if (vfx.IsMatch(key))
|
||||||
return true;
|
{
|
||||||
|
var x = vfx.prefab;
|
||||||
|
return x;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
value = null;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -59,6 +59,7 @@ namespace BITKit.Vehicles
|
|||||||
private bool isBraking;
|
private bool isBraking;
|
||||||
private readonly ValidHandle highSpeedHandle = new();
|
private readonly ValidHandle highSpeedHandle = new();
|
||||||
private IUnityEntity _unityEntity;
|
private IUnityEntity _unityEntity;
|
||||||
|
public Rigidbody Rigidbody => rigidbody;
|
||||||
|
|
||||||
[Inject(true)]
|
[Inject(true)]
|
||||||
private IHealth _health;
|
private IHealth _health;
|
||||||
|
@@ -8,7 +8,8 @@
|
|||||||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||||
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
||||||
"GUID:f51ebe6a0ceec4240a699833d6309b23"
|
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||||
|
"GUID:045a42f233e479d41adc32d02b99631e"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
|
@@ -13,7 +13,8 @@ namespace BITKit.OpenWorld
|
|||||||
[SerializeField,ReadOnly] private int id;
|
[SerializeField,ReadOnly] private int id;
|
||||||
[SerializeField] protected Vector3 size = Vector3.one;
|
[SerializeField] protected Vector3 size = Vector3.one;
|
||||||
[SerializeField] protected Vector3 offset = Vector3.one * 0.5f;
|
[SerializeField] protected Vector3 offset = Vector3.one * 0.5f;
|
||||||
public Bounds GetBounds()=>new Bounds(transform.position+transform.rotation * offset,transform.rotation * size);
|
public Bounds GetBounds() => _bounds;
|
||||||
|
private Bounds _bounds;
|
||||||
public Node<IWorldChunkObject> ParentNode { get; set; }
|
public Node<IWorldChunkObject> ParentNode { get; set; }
|
||||||
public void QuadTree_Root_Initialized(IQuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>> root)
|
public void QuadTree_Root_Initialized(IQuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>> root)
|
||||||
{
|
{
|
||||||
@@ -30,6 +31,7 @@ namespace BITKit.OpenWorld
|
|||||||
}
|
}
|
||||||
protected virtual void Start()
|
protected virtual void Start()
|
||||||
{
|
{
|
||||||
|
_bounds= new Bounds(transform.position+transform.rotation * offset,transform.rotation * size);
|
||||||
UnityWorldChunkService.Singleton.Register(this);
|
UnityWorldChunkService.Singleton.Register(this);
|
||||||
destroyCancellationToken.Register(Dispose);
|
destroyCancellationToken.Register(Dispose);
|
||||||
}
|
}
|
||||||
|
@@ -18,8 +18,17 @@ namespace BITKit.OpenWorld
|
|||||||
[SerializeField] private ChunkBehaviour chunkBehaviour;
|
[SerializeField] private ChunkBehaviour chunkBehaviour;
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
chunkBehaviour.OnLodChangedEvent += OnLodChanged;
|
try
|
||||||
if(colliders is {Length:0})colliders = GetComponentsInChildren<Collider>();
|
{
|
||||||
|
chunkBehaviour.OnLodChangedEvent += OnLodChanged;
|
||||||
|
if(colliders is {Length:0})colliders = GetComponentsInChildren<Collider>();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
BIT4Log.Warning<ColliderChunkObject>(gameObject.name);
|
||||||
|
BIT4Log.LogException(e);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
private void OnLodChanged(int arg1, int arg2)
|
private void OnLodChanged(int arg1, int arg2)
|
||||||
{
|
{
|
||||||
@@ -30,22 +39,28 @@ namespace BITKit.OpenWorld
|
|||||||
{
|
{
|
||||||
x.enabled = enabledCollider;
|
x.enabled = enabledCollider;
|
||||||
}
|
}
|
||||||
|
catch (UnassignedReferenceException)
|
||||||
|
{
|
||||||
|
GetCollidersInChildren();
|
||||||
|
OnLodChanged(arg1, arg2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
BIT4Log.Warning<ColliderChunkObject>(gameObject.name);
|
BIT4Log.Warning<ColliderChunkObject>(gameObject.name);
|
||||||
BIT4Log.LogException(e);
|
BIT4Log.LogException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if UNITY_EDITOR
|
|
||||||
[BIT]
|
[BIT]
|
||||||
private void GetCollidersInChildren()
|
private void GetCollidersInChildren()
|
||||||
{
|
{
|
||||||
colliders = GetComponentsInChildren<Collider>();
|
colliders = GetComponentsInChildren<Collider>();
|
||||||
|
#if UNITY_EDITOR
|
||||||
EditorUtility.SetDirty(this);
|
EditorUtility.SetDirty(this);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,8 +2,11 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using BITKit.SceneManagement;
|
||||||
|
using Cysharp.Threading.Tasks;
|
||||||
using Quadtree;
|
using Quadtree;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Pool;
|
||||||
|
|
||||||
|
|
||||||
namespace BITKit.OpenWorld
|
namespace BITKit.OpenWorld
|
||||||
@@ -21,13 +24,16 @@ namespace BITKit.OpenWorld
|
|||||||
private readonly ConcurrentDictionary<int, IWorldChunkObject> dictionary=new();
|
private readonly ConcurrentDictionary<int, IWorldChunkObject> dictionary=new();
|
||||||
|
|
||||||
[SerializeReference, SubclassSelector] private ITicker ticker;
|
[SerializeReference, SubclassSelector] private ITicker ticker;
|
||||||
|
[SerializeReference, SubclassSelector] private ISceneService sceneService;
|
||||||
[SerializeField, ReadOnly] private int count;
|
[SerializeField, ReadOnly] private int count;
|
||||||
|
[SerializeField, ReadOnly] private int tickTaskCount;
|
||||||
[SerializeField] private bool drawBounds;
|
[SerializeField] private bool drawBounds;
|
||||||
[SerializeField, Range(0, 1024)] private int[] lodDistances;
|
[SerializeField, Range(0, 1024)] private int[] lodDistances;
|
||||||
[SerializeField] private Vector3 size;
|
[SerializeField] private Vector3 size;
|
||||||
private Camera _camera;
|
private Camera _camera;
|
||||||
private readonly HashSet<int> cacheList = new();
|
private readonly HashSet<int> cacheList = new();
|
||||||
|
private readonly Queue<(int, IWorldChunkObject)> lodQueue=new();
|
||||||
|
private bool isBusy;
|
||||||
protected virtual void Awake()
|
protected virtual void Awake()
|
||||||
{
|
{
|
||||||
Singleton = (T) this;
|
Singleton = (T) this;
|
||||||
@@ -35,20 +41,35 @@ namespace BITKit.OpenWorld
|
|||||||
|
|
||||||
protected virtual void Start()
|
protected virtual void Start()
|
||||||
{
|
{
|
||||||
|
sceneService?.RegisterLoadTaskAsync(LoadTask);
|
||||||
ticker.Add(OnTick);
|
ticker.Add(OnTick);
|
||||||
destroyCancellationToken.Register(Dispose);
|
destroyCancellationToken.Register(Dispose);
|
||||||
_quadtree = new QuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>>(transform.position, size);
|
_quadtree = new QuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>>(transform.position, size);
|
||||||
_camera = Camera.main;
|
_camera = Camera.main;
|
||||||
}
|
}
|
||||||
private void Dispose()
|
private async UniTask LoadTask()
|
||||||
{
|
{
|
||||||
|
var frame=0;
|
||||||
|
while (count is 0 || frame++<32)
|
||||||
|
{
|
||||||
|
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Dispose()
|
||||||
|
{
|
||||||
|
sceneService?.UnRegisterLoadTaskAsync(LoadTask);
|
||||||
ticker.Remove(OnTick);
|
ticker.Remove(OnTick);
|
||||||
_registerQueue.Clear();
|
_registerQueue.Clear();
|
||||||
_unregisterQueue.Clear();
|
_unregisterQueue.Clear();
|
||||||
}
|
}
|
||||||
protected virtual void OnTick(float deltaTime)
|
protected virtual async void OnTick(float deltaTime)
|
||||||
{
|
{
|
||||||
if (!enabled) return;
|
if (!enabled) return;
|
||||||
|
if (isBusy) return;
|
||||||
|
|
||||||
|
isBusy = true;
|
||||||
while (_unregisterQueue.TryDequeue(out var obj))
|
while (_unregisterQueue.TryDequeue(out var obj))
|
||||||
{
|
{
|
||||||
_quadtree.Remove(obj);
|
_quadtree.Remove(obj);
|
||||||
@@ -63,28 +84,76 @@ namespace BITKit.OpenWorld
|
|||||||
}
|
}
|
||||||
|
|
||||||
var cameraPosition = _camera.transform.position;
|
var cameraPosition = _camera.transform.position;
|
||||||
|
|
||||||
|
var cycle = 0;
|
||||||
|
|
||||||
for (var index = 0; index < lodDistances.Length; index++)
|
await UniTask.SwitchToThreadPool();
|
||||||
|
|
||||||
|
foreach (var chunkObject in _quadtree.Find(new Bounds(cameraPosition, Vector3.one * (lodDistances[^1]+lodDistances[0]))))
|
||||||
{
|
{
|
||||||
var distance = lodDistances[index];
|
if (cycle++ > 64)
|
||||||
foreach (var chunkObject in _quadtree.Find(new Bounds(cameraPosition, Vector3.one * distance)))
|
|
||||||
{
|
{
|
||||||
if (cacheList.Contains(chunkObject.Id)) continue;
|
cycle = 0;
|
||||||
cacheList.Add(chunkObject.Id);
|
await UniTask.NextFrame();
|
||||||
|
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||||
var lod = chunkObject.Lod;
|
|
||||||
if (lod == index) continue;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
chunkObject.Lod = index;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
BIT4Log.LogException(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var distance = Vector3.Distance(cameraPosition, chunkObject.GetBounds().center);
|
||||||
|
//var distance = Vector3.Distance(cameraPosition, chunkObject.GetBounds().ClosestPoint(cameraPosition));
|
||||||
|
if (cacheList.Contains(chunkObject.Id)) continue;
|
||||||
|
cacheList.Add(chunkObject.Id);
|
||||||
|
|
||||||
|
var lod = -1;
|
||||||
|
|
||||||
|
for (var i = 0; i < lodDistances.Length; i++)
|
||||||
|
{
|
||||||
|
if (!(distance < lodDistances[i])) continue;
|
||||||
|
lod = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(chunkObject.Lod==lod)continue;
|
||||||
|
//chunkObject.Lod = lod;
|
||||||
|
lodQueue.Enqueue((lod,chunkObject));
|
||||||
|
}
|
||||||
|
// for (var index = 0; index < lodDistances.Length; index++)
|
||||||
|
// {
|
||||||
|
// var distance = lodDistances[index];
|
||||||
|
// foreach (var chunkObject in _quadtree.Find(new Bounds(cameraPosition, Vector3.one * distance)))
|
||||||
|
// {
|
||||||
|
// if (cacheList.Contains(chunkObject.Id)) continue;
|
||||||
|
// cacheList.Add(chunkObject.Id);
|
||||||
|
//
|
||||||
|
// var lod = chunkObject.Lod;
|
||||||
|
// if (lod == index) continue;
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// chunkObject.Lod = index;
|
||||||
|
// }
|
||||||
|
// catch (Exception e)
|
||||||
|
// {
|
||||||
|
// BIT4Log.LogException(e);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
await UniTask.SwitchToMainThread();
|
||||||
|
tickTaskCount = lodQueue.Count;
|
||||||
|
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||||
|
|
||||||
|
cycle = 0;
|
||||||
|
while (lodQueue.TryDequeue(out var value))
|
||||||
|
{
|
||||||
|
if (cycle++ > 8)
|
||||||
|
{
|
||||||
|
cycle = 0;
|
||||||
|
await UniTask.NextFrame();
|
||||||
|
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||||
|
}
|
||||||
|
value.Item2.Lod = value.Item1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isBusy = false;
|
||||||
cacheList.Clear();
|
cacheList.Clear();
|
||||||
}
|
}
|
||||||
private void OnDrawGizmosSelected()
|
private void OnDrawGizmosSelected()
|
||||||
|
@@ -25,7 +25,7 @@ namespace BITKit.OpenWorld
|
|||||||
if (_sceneHandle is not null) return;
|
if (_sceneHandle is not null) return;
|
||||||
var stopWatcher = new System.Diagnostics.Stopwatch();
|
var stopWatcher = new System.Diagnostics.Stopwatch();
|
||||||
stopWatcher.Start();
|
stopWatcher.Start();
|
||||||
_sceneHandle = YooAssets.LoadSceneAsync(sceneName.Value,LoadSceneMode.Additive,suspendLoad:true,priority:8);
|
_sceneHandle = YooAssets.LoadSceneAsync(sceneName.Value,LoadSceneMode.Additive,priority:8);
|
||||||
await _sceneHandle;
|
await _sceneHandle;
|
||||||
stopWatcher.Stop();
|
stopWatcher.Stop();
|
||||||
Debug.Log($"加载场景 {sceneName.Value} 耗时 {stopWatcher.ElapsedMilliseconds}ms");
|
Debug.Log($"加载场景 {sceneName.Value} 耗时 {stopWatcher.ElapsedMilliseconds}ms");
|
||||||
|
@@ -70,7 +70,7 @@ namespace BITKit.GameEditor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@@ -18,7 +18,7 @@ namespace BITKit.GameEditor
|
|||||||
protected readonly List<T> List=new();
|
protected readonly List<T> List=new();
|
||||||
|
|
||||||
private ListView _listView;
|
private ListView _listView;
|
||||||
private VisualElement _container;
|
protected VisualElement _container { get; private set; }
|
||||||
private Button _createButton;
|
private Button _createButton;
|
||||||
|
|
||||||
private void OnEnable()
|
private void OnEnable()
|
||||||
@@ -99,7 +99,7 @@ namespace BITKit.GameEditor
|
|||||||
$"{GetType().Name} 已初始化,从{AssetsPath}获取到{List.Count}个{typeof(T).Name}");
|
$"{GetType().Name} 已初始化,从{AssetsPath}获取到{List.Count}个{typeof(T).Name}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ItemsChosen(IEnumerable<object> obj)
|
protected virtual void ItemsChosen(IEnumerable<object> obj)
|
||||||
{
|
{
|
||||||
var selected = obj.FirstOrDefault() as Object;
|
var selected = obj.FirstOrDefault() as Object;
|
||||||
var serializedObject = new SerializedObject(selected);
|
var serializedObject = new SerializedObject(selected);
|
||||||
@@ -167,6 +167,7 @@ namespace BITKit.GameEditor
|
|||||||
).ToArray();
|
).ToArray();
|
||||||
List.AddRange(allItem.Cast<T>());
|
List.AddRange(allItem.Cast<T>());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void CreateScriptableObject(string name)
|
protected virtual void CreateScriptableObject(string name)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(name))
|
if (string.IsNullOrEmpty(name))
|
||||||
@@ -178,6 +179,8 @@ namespace BITKit.GameEditor
|
|||||||
|
|
||||||
if (EditorUtility.DisplayDialog("创建", $"是否创建{name}与{path}?", "是", "否") is false) return;
|
if (EditorUtility.DisplayDialog("创建", $"是否创建{name}与{path}?", "是", "否") is false) return;
|
||||||
|
|
||||||
|
new DirectoryInfo(Path.GetDirectoryName(path)!).Create();
|
||||||
|
|
||||||
var item = CreateInstance<T>();
|
var item = CreateInstance<T>();
|
||||||
item.name = name;
|
item.name = name;
|
||||||
AssetDatabase.CreateAsset(item, path);
|
AssetDatabase.CreateAsset(item, path);
|
||||||
|
@@ -3,7 +3,9 @@ using System.Collections;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using MeshCombineStudio;
|
using MeshCombineStudio;
|
||||||
using NGS.AdvancedCullingSystem.Dynamic;
|
using NGS.AdvancedCullingSystem.Dynamic;
|
||||||
|
using UnityEditor.Build;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.Events;
|
||||||
#if UNITY_EDITOR
|
#if UNITY_EDITOR
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
#endif
|
#endif
|
||||||
@@ -12,15 +14,21 @@ namespace BITKit.OpenWorld
|
|||||||
public class OpenWorldCombiner : MonoBehaviour
|
public class OpenWorldCombiner : MonoBehaviour
|
||||||
{
|
{
|
||||||
[SerializeField] private MeshCombiner meshCombiner;
|
[SerializeField] private MeshCombiner meshCombiner;
|
||||||
|
|
||||||
|
[SerializeField] private UnityEvent onCombiningReady;
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private bool allowCullingSource = true;
|
||||||
|
|
||||||
private void Start()
|
private void Start()
|
||||||
{
|
{
|
||||||
|
meshCombiner.onCombiningReady +=x=> onCombiningReady.Invoke();
|
||||||
meshCombiner.onCombiningReady += AddCullingSource;
|
meshCombiner.onCombiningReady += AddCullingSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddCullingSource(MeshCombiner meshcombiner)
|
private void AddCullingSource(MeshCombiner meshcombiner)
|
||||||
{
|
{
|
||||||
if (enabled)
|
if (allowCullingSource)
|
||||||
AddCullingSource();
|
AddCullingSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -12,20 +12,35 @@ namespace BITKit
|
|||||||
public string questName;
|
public string questName;
|
||||||
public string qeustDescription;
|
public string qeustDescription;
|
||||||
public BBParameter<QuestSystem.Info> output;
|
public BBParameter<QuestSystem.Info> output;
|
||||||
|
|
||||||
|
private bool isInitiated;
|
||||||
|
private void Disposed()
|
||||||
|
{
|
||||||
|
if (output.isNoneOrNull) return;
|
||||||
|
if(output.value.State is QuestSystem.State.InProcess)
|
||||||
|
{
|
||||||
|
BIT4Log.Log<CreateQuest>($"任务{output.value.Name}已取消");
|
||||||
|
QuestSystem.Cancel(output.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
protected override void OnExecute()
|
protected override void OnExecute()
|
||||||
{
|
{
|
||||||
var quest = QuestSystem.Create(questName, qeustDescription);
|
var quest = QuestSystem.Create(questName, qeustDescription);
|
||||||
if (output.isDefined)
|
if (output.isDefined)
|
||||||
output.SetValue(quest);
|
output.SetValue(quest);
|
||||||
EndAction();
|
EndAction();
|
||||||
}
|
|
||||||
protected override void OnStop(bool interrupted)
|
if(isInitiated)return;
|
||||||
{
|
agent.As<MonoBehaviour>().destroyCancellationToken.Register(Disposed);
|
||||||
base.OnStop(interrupted);
|
isInitiated = true;
|
||||||
if (!interrupted) return;
|
; }
|
||||||
if (QuestSystem.quests.TryGetValue(output.value, out var info) &&
|
// protected override void OnStop(bool interrupted)
|
||||||
info.State == QuestSystem.State.InProcess)
|
// {
|
||||||
QuestSystem.Cancel(output.value);
|
// base.OnStop(interrupted);
|
||||||
}
|
// if (!interrupted) return;
|
||||||
|
// if (QuestSystem.quests.TryGetValue(output.value, out var info) &&
|
||||||
|
// info.State == QuestSystem.State.InProcess)
|
||||||
|
// QuestSystem.Cancel(output.value);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -34,7 +34,6 @@ namespace BITKit
|
|||||||
{
|
{
|
||||||
blackboard.SetVariableValue("HP", hp);
|
blackboard.SetVariableValue("HP", hp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnEntryOverride(bool @override)
|
public void OnEntryOverride(bool @override)
|
||||||
{
|
{
|
||||||
_allow.SetDisableElements(this,@override);
|
_allow.SetDisableElements(this,@override);
|
||||||
|
@@ -15,7 +15,7 @@ namespace BITKit.NodeCanvas
|
|||||||
public BBParameter<Transform> target;
|
public BBParameter<Transform> target;
|
||||||
protected override void OnExecute()
|
protected override void OnExecute()
|
||||||
{
|
{
|
||||||
target.SetValue(sensor.value.CurrentTarget);
|
//target.SetValue(sensor.value.CurrentTarget);
|
||||||
EndAction();
|
EndAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user