This commit is contained in:
parent
37e7fcea51
commit
c798b224be
|
@ -63,6 +63,11 @@ namespace BITKit
|
|||
/// </summary>
|
||||
ItemQuality Quality { get; }
|
||||
bool CopyItemsFrom(IBasicItem item);
|
||||
/// <summary>
|
||||
/// 价值
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
int Value=>10;
|
||||
}
|
||||
/// <summary>
|
||||
/// 可配置化物品,通常用于配置
|
||||
|
@ -84,6 +89,7 @@ namespace BITKit
|
|||
public string AddressablePath { get; set; }
|
||||
public string Description;
|
||||
public ItemQuality Quality;
|
||||
public int Value { get; set; }
|
||||
/// <summary>
|
||||
/// 本地属性
|
||||
/// </summary>
|
||||
|
@ -122,6 +128,7 @@ namespace BITKit
|
|||
|
||||
public bool CopyItemsFrom(IBasicItem item)
|
||||
{
|
||||
Value = item.Value;
|
||||
Id=item.Id;
|
||||
Name = item.Name;
|
||||
AddressablePath = item.AddressablePath;
|
||||
|
|
|
@ -75,6 +75,21 @@ namespace BITKit
|
|||
/// 已重构Items的回调
|
||||
/// </summary>
|
||||
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 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)
|
||||
{
|
||||
return index >= 0 && index < self.Count();
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: e517c312e735e1042b911efc79deb1f6
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"name": "BITKit.Probability",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": true
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 2f7d7f857f30f484ea163931f3bc4e0a
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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
|
||||
guid: d6c28a6107497be44bfecb5e31b960c5
|
||||
guid: 8e4f1cbf25a4f494d89fc3831dbc82ab
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
|
@ -70,87 +70,84 @@ namespace BITKit
|
|||
{
|
||||
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>()
|
||||
{
|
||||
return (T)properties[typeof(T).FullName];
|
||||
return properties.OfType<T>().First();
|
||||
}
|
||||
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>()
|
||||
{
|
||||
return properties.ContainsKey(typeof(T).FullName);
|
||||
return properties.OfType<T>().FirstOrDefault() is not null;
|
||||
}
|
||||
|
||||
public T GetOrCreateProperty<T>()
|
||||
{
|
||||
return GetOrAddProperty(Activator.CreateInstance<T>);
|
||||
}
|
||||
|
||||
public T GetOrAddProperty<T>(Func<T> addFactory)
|
||||
{
|
||||
if (properties.TryGetValue(typeof(T).FullName, out var x))
|
||||
foreach (var obj in properties)
|
||||
{
|
||||
return (T)x;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddPropertyInternal(x =addFactory.Invoke());
|
||||
//properties.Add(typeof(T).FullName, x = addFactory.Invoke());
|
||||
return (T)x;
|
||||
if (obj is T t) return t;
|
||||
}
|
||||
T x;
|
||||
properties.Add(x = addFactory.Invoke());
|
||||
return x;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
else
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
value=default(T);
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
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);
|
||||
return true;
|
||||
properties.Remove(value);
|
||||
removed = true;
|
||||
}
|
||||
// if(properties.TryGetValue(typeof(T).FullName, out var x))
|
||||
// {
|
||||
// properties.Remove(typeof(T).Name);
|
||||
// return true;
|
||||
// }
|
||||
return false;
|
||||
return removed;
|
||||
}
|
||||
public bool TrySetProperty<T>(T value)
|
||||
{
|
||||
bool result = false;
|
||||
foreach (var pair in properties.Where(x=>x.Value is T).ToArray())
|
||||
var current = properties.OfType<T>().FirstOrDefault();
|
||||
if (current is not null)
|
||||
{
|
||||
properties[pair.Key] = value;
|
||||
result = true;
|
||||
properties.Remove(current);
|
||||
return true;
|
||||
}
|
||||
return result;
|
||||
// if (properties.TryGetValue(typeof(T).FullName, out var x))
|
||||
// {
|
||||
// properties[typeof(T).FullName] = value;
|
||||
// return true;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
properties.Add(value);
|
||||
return false;
|
||||
}
|
||||
public object[] GetProperties()=>properties.Values.Distinct().ToArray();
|
||||
|
||||
public object[] GetProperties() => properties.ToArray();
|
||||
|
||||
public void Read(BinaryReader r)
|
||||
{
|
||||
|
@ -174,23 +171,8 @@ namespace BITKit
|
|||
public bool CopyPropertiesFrom(IPropertable propertable)
|
||||
{
|
||||
ClearProperties();
|
||||
foreach (var x in propertable.GetProperties())
|
||||
{
|
||||
AddPropertyInternal(x);
|
||||
}
|
||||
properties.AddRange( propertable.GetProperties());;
|
||||
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
|
||||
{
|
||||
int Hash { get; }
|
||||
string[] GetTags();
|
||||
}
|
||||
}
|
|
@ -145,6 +145,13 @@ namespace BITKit
|
|||
{
|
||||
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)
|
||||
{
|
||||
try
|
||||
|
|
|
@ -26,6 +26,7 @@ RenderTexture:
|
|||
m_UseDynamicScale: 0
|
||||
m_BindMS: 0
|
||||
m_EnableCompatibleFormat: 1
|
||||
m_EnableRandomWrite: 0
|
||||
m_TextureSettings:
|
||||
serializedVersion: 2
|
||||
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.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using BITKit.Mod;
|
||||
using UnityEngine;
|
||||
|
@ -15,6 +16,7 @@ namespace BITKit.Animations
|
|||
public class ScriptableMotionMatchingService : MonoBehaviour,IMotionMatchingService
|
||||
{
|
||||
internal static ScriptableMotionMatchingService Singleton { get; private set; }
|
||||
internal static readonly ConcurrentDictionary<int, IMotionMatchingObject> Cache = new();
|
||||
|
||||
private ObjectMatcher<string,IMotionMatchingObject> _objects;
|
||||
|
||||
|
@ -40,16 +42,23 @@ namespace BITKit.Animations
|
|||
|
||||
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()
|
||||
{
|
||||
Cache.Clear();
|
||||
var list = new List<ScriptableMotionMatchingObject>();
|
||||
var tags = new []{nameof(IMotionMatchingObject)};
|
||||
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))
|
||||
{
|
||||
var collider = raycastHit.collider;
|
||||
if (collider.isTrigger) return false;
|
||||
switch (collider)
|
||||
{
|
||||
case MeshCollider meshCollider:
|
||||
|
|
|
@ -4,7 +4,7 @@ using System.Collections.Generic;
|
|||
using BITKit.Core.Tuple;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.Physics
|
||||
namespace BITKit
|
||||
{
|
||||
[Serializable]
|
||||
public class JointConfigure
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using BITKit.Events;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BITKit.Physics
|
||||
namespace BITKit
|
||||
{
|
||||
public class Prop_Physics : MonoBehaviour
|
||||
{
|
||||
|
|
|
@ -41,6 +41,15 @@ namespace BITKit.SceneManagement
|
|||
/// 场景加载完成的回调
|
||||
/// </summary>
|
||||
event Action<string> OnSceneLoaded;
|
||||
/// <summary>
|
||||
/// 注册加载任务
|
||||
/// </summary>
|
||||
void RegisterLoadTaskAsync(Func<UniTask> task);
|
||||
/// <summary>
|
||||
/// 注销加载任务
|
||||
/// </summary>
|
||||
/// <param name="task"></param>
|
||||
void UnRegisterLoadTaskAsync(Func<UniTask> task);
|
||||
/// <summary>
|
||||
/// 当开始卸载场景时
|
||||
/// </summary>
|
||||
|
@ -89,6 +98,16 @@ namespace BITKit.SceneManagement
|
|||
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
|
||||
{
|
||||
add => _sceneServiceImplementation1.OnUnloadScene += value;
|
||||
|
|
|
@ -58,6 +58,16 @@ namespace BITKit.SceneManagement
|
|||
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
|
||||
{
|
||||
add => _sceneServiceImplementation.OnUnloadScene += value;
|
||||
|
@ -198,9 +208,15 @@ namespace BITKit.SceneManagement
|
|||
OnSceneLoadProgress?.Invoke(sceneName, progress);
|
||||
}
|
||||
LoadedObjects.Add(sceneName, handle.SceneObject);
|
||||
|
||||
OnSceneLoadProgress?.Invoke(sceneName, 1);
|
||||
await Task.Delay(384, cancellationToken);
|
||||
|
||||
foreach (var x in _onSceneLoadedAsyncList.ToArray())
|
||||
{
|
||||
await x.Invoke();
|
||||
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||
}
|
||||
|
||||
OnSceneLoaded?.Invoke(sceneName);
|
||||
stopwatchWatcher.Stop();
|
||||
// if (activateOnLoad is false)
|
||||
|
@ -252,6 +268,16 @@ namespace BITKit.SceneManagement
|
|||
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> OnSceneUnloaded;
|
||||
}
|
||||
|
|
|
@ -1,49 +1,49 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
using System.Linq;
|
||||
using UnityEditor.Search;
|
||||
|
||||
namespace BITKit.Sensors
|
||||
{
|
||||
public interface IAudioObject
|
||||
{
|
||||
float GetVolume();
|
||||
}
|
||||
public class AudioSensor : Sensor
|
||||
public class AudioSensor : MonoBehaviour,ISensor
|
||||
{
|
||||
[Header(Constant.Header.Settings)]
|
||||
public float radius;
|
||||
[Header(Constant.Header.InternalVariables)]
|
||||
IAudioObject currentAudioObject;
|
||||
Collider currentCollider;
|
||||
Collider[] colliders = new Collider[32];
|
||||
public override IEnumerable<Transform> Get() => detected;
|
||||
public override UniTask Execute()
|
||||
[SerializeField] private bool autoUpdate;
|
||||
[SerializeField]private float radius;
|
||||
private readonly CacheList<Transform> cache = new();
|
||||
private void OnEnable()
|
||||
{
|
||||
var cacheList = ListPool<Transform>.Get();
|
||||
for (int i = 0; i < Physics.OverlapSphereNonAlloc(transform.position, radius, colliders, detectLayer); i++)
|
||||
Id = GetInstanceID();
|
||||
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];
|
||||
if (IsValid(currentCollider))
|
||||
{
|
||||
cacheList.Add(currentCollider.transform);
|
||||
}
|
||||
var distance = Vector3.Distance(position, x.Position);
|
||||
if(distance>radius) continue;
|
||||
cache.Add(x.Transform);
|
||||
}
|
||||
detected = cacheList.ToArray();
|
||||
ListPool<Transform>.Release(cacheList);
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
public override bool IsValid(Collider _collider)
|
||||
{
|
||||
if (ignoreColliders.Contains(_collider) is false)
|
||||
if (Vector3.Distance(transform.position, _collider.transform.position) <= radius)
|
||||
if (_collider.TryGetComponent<IAudioObject>(out currentAudioObject))
|
||||
{
|
||||
return currentAudioObject.GetVolume() >= 1;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public override float GetDistance() => radius;
|
||||
public int Id { get; set; }
|
||||
public IEnumerable<Transform> Get() => cache.ValueArray;
|
||||
public bool IsValid(Collider _collider) => false;
|
||||
public float GetDistance() => radius;
|
||||
public bool AutoUpdate=>autoUpdate;
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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:be17a8778dbfe454890ed8279279e153",
|
||||
"GUID:14fe60d984bf9f84eac55c6ea033a8f4",
|
||||
"GUID:9400d40641bab5b4a9702f65bf5c6eb5"
|
||||
"GUID:9400d40641bab5b4a9702f65bf5c6eb5",
|
||||
"GUID:1193c2664d97cc049a6e4c486c6bce71"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace BITKit.Sensors
|
|||
/// </summary>
|
||||
public interface ISensor
|
||||
{
|
||||
int Id { get; }
|
||||
/// <summary>
|
||||
/// 自动更新
|
||||
/// </summary>
|
||||
|
@ -45,7 +46,7 @@ namespace BITKit.Sensors
|
|||
/// 传感器执行检测
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
UniTask Execute();
|
||||
UniTask Execute(float delta);
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
|
@ -53,6 +54,8 @@ namespace BITKit.Sensors
|
|||
{
|
||||
[SerializeField] private GameObject gameObject;
|
||||
private ISensor _sensorImplementation => gameObject.GetComponent<ISensor>();
|
||||
public int Id => _sensorImplementation.Id;
|
||||
|
||||
public IEnumerable<Transform> Get()
|
||||
{
|
||||
return _sensorImplementation.Get();
|
||||
|
@ -67,10 +70,9 @@ namespace BITKit.Sensors
|
|||
{
|
||||
return _sensorImplementation.GetDistance();
|
||||
}
|
||||
|
||||
public UniTask Execute()
|
||||
public UniTask Execute(float delta)
|
||||
{
|
||||
return _sensorImplementation.Execute();
|
||||
return _sensorImplementation.Execute(delta);
|
||||
}
|
||||
}
|
||||
[System.Serializable]
|
||||
|
@ -78,6 +80,8 @@ namespace BITKit.Sensors
|
|||
{
|
||||
[SerializeField] private MonoBehaviour monoBehaviour;
|
||||
private ISensor _sensorImplementation=>monoBehaviour as ISensor;
|
||||
public int Id => _sensorImplementation.Id;
|
||||
|
||||
public IEnumerable<Transform> Get()
|
||||
{
|
||||
return _sensorImplementation.Get();
|
||||
|
@ -93,9 +97,9 @@ namespace BITKit.Sensors
|
|||
return _sensorImplementation.GetDistance();
|
||||
}
|
||||
|
||||
public UniTask Execute()
|
||||
public UniTask Execute(float delta)
|
||||
{
|
||||
return _sensorImplementation.Execute();
|
||||
return _sensorImplementation.Execute(delta);
|
||||
}
|
||||
}
|
||||
public abstract class Sensor : MonoBehaviour, ISensor
|
||||
|
@ -106,16 +110,15 @@ namespace BITKit.Sensors
|
|||
[Header(Constant.Header.Gameobjects)]
|
||||
public Collider[] ignoreColliders;
|
||||
[Header(Constant.Header.InternalVariables)]
|
||||
[NonSerialized]
|
||||
[SerializeField,ReadOnly]
|
||||
public Transform[] detected = Array.Empty<Transform>();
|
||||
public abstract IEnumerable<Transform> Get();
|
||||
public abstract bool IsValid(Collider _collider);
|
||||
public abstract UniTask Execute();
|
||||
public abstract float GetDistance();
|
||||
|
||||
public virtual UniTask Execute(float delta)=>UniTask.CompletedTask;
|
||||
public int Id { get; private set; }
|
||||
bool ISensor.AutoUpdate => autoUpdate;
|
||||
|
||||
protected int Id;
|
||||
protected Transform Transform;
|
||||
|
||||
protected virtual void OnEnable()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 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 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.Pool;
|
||||
using UnityEngine.Profiling;
|
||||
using Physics=UnityEngine.Physics;
|
||||
|
||||
namespace BITKit.Sensors
|
||||
{
|
||||
public class RangeSensor : Sensor
|
||||
{
|
||||
[Header(Constant.Header.Settings)]
|
||||
public float radius;
|
||||
[Header(Constant.Header.Settings)] public float radius;
|
||||
public int fov;
|
||||
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()
|
||||
{
|
||||
if (!_detectedDoubleBuffer.TryGetRelease(out var newRelease)) return _detectedBuffer;
|
||||
|
@ -33,12 +34,13 @@ namespace BITKit.Sensors
|
|||
Profiler.EndSample();
|
||||
return _detectedBuffer;
|
||||
}
|
||||
private readonly DoubleBuffer<IEnumerable<Transform>> _detectedDoubleBuffer=new();
|
||||
private IEnumerable<Transform> _detectedBuffer;
|
||||
|
||||
|
||||
public override UniTask Execute()
|
||||
private readonly DoubleBuffer<IEnumerable<Transform>> _detectedDoubleBuffer = new();
|
||||
private IEnumerable<Transform> _detectedBuffer=Array.Empty<Transform>();
|
||||
|
||||
public override UniTask Execute(float delta)
|
||||
{
|
||||
tempHashSet.Clear();
|
||||
var length = Physics.OverlapSphereNonAlloc(Transform.position, radius, colliders, detectLayer);
|
||||
Profiler.BeginSample("Filter Detected Colliders");
|
||||
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):
|
||||
return 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;
|
||||
default:
|
||||
return true;
|
||||
|
@ -62,18 +64,21 @@ namespace BITKit.Sensors
|
|||
}
|
||||
|
||||
public override float GetDistance() => radius;
|
||||
|
||||
private bool CheckFov(ref Collider _collider)
|
||||
{
|
||||
var _dir = _collider.transform.position - transform.position;
|
||||
if (_dir.sqrMagnitude <= 0) return false;
|
||||
var dir = Quaternion.LookRotation(_dir);
|
||||
return Vector3.Dot(transform.forward, _dir) > 0 && fov > Quaternion.Angle(transform.rotation, dir);
|
||||
var _dir = _collider.bounds.center - transform.position;
|
||||
if (_dir.sqrMagnitude <= 0) return false;
|
||||
var dir = Quaternion.LookRotation(_dir);
|
||||
return Vector3.Dot(transform.forward, _dir) > 0 && fov > Quaternion.Angle(transform.rotation, dir);
|
||||
}
|
||||
|
||||
private bool CheckSight(ref Collider _collider)
|
||||
{
|
||||
if (!requireSight) return false;
|
||||
var transform1 = _collider.transform;
|
||||
var position = transform1.position;
|
||||
var position = _collider.bounds.center;
|
||||
//是检测bounds的顶部
|
||||
position.y += _collider.bounds.extents.y;
|
||||
var location = new Location(Transform);
|
||||
var length = Physics.RaycastNonAlloc(
|
||||
location.position,
|
||||
|
@ -82,23 +87,32 @@ namespace BITKit.Sensors
|
|||
Vector3.Distance(location, position),
|
||||
blockLayer
|
||||
);
|
||||
|
||||
switch (length)
|
||||
{
|
||||
case 0:
|
||||
Debug.DrawLine(location, position, Color.green, 1);
|
||||
return true;
|
||||
case 1:
|
||||
if (hits[0].collider == _collider)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (hits.Take(length).Any(x => ignoreColliders.Contains(x.collider) is false))
|
||||
return hits[0].collider == _collider;
|
||||
default:
|
||||
var collider1 = _collider;
|
||||
if (hits.Take(length).Any(Predicate))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace BITKit.Sensors
|
|||
public float distance;
|
||||
public override IEnumerable<Transform> Get() => detected;
|
||||
private readonly RaycastHit[] raycasts = new RaycastHit[16];
|
||||
public override UniTask Execute()
|
||||
public override UniTask Execute(float delta)
|
||||
{
|
||||
var _transform = transform;
|
||||
var forward = _transform.forward;
|
||||
|
@ -46,7 +46,7 @@ namespace BITKit.Sensors
|
|||
{
|
||||
if (autoUpdate)
|
||||
{
|
||||
Execute().Forget();
|
||||
Execute(Time.deltaTime).Forget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Cysharp.Threading.Tasks;
|
||||
|
@ -10,6 +11,7 @@ namespace BITKit.Sensors
|
|||
public class SensorQueue : MonoBehaviour
|
||||
{
|
||||
internal static readonly Dictionary<int,ISensor> Sensors=new();
|
||||
internal static readonly ConcurrentDictionary<int, float> LastDetectedTime = new();
|
||||
private static bool IsDirty;
|
||||
|
||||
[SerializeField,ReadOnly] private int _position;
|
||||
|
@ -32,10 +34,25 @@ namespace BITKit.Sensors
|
|||
}
|
||||
|
||||
[SerializeField] private MonoBehaviour[] sensors;
|
||||
|
||||
private void Update()
|
||||
[SerializeReference,SubclassSelector] private ITicker ticker;
|
||||
|
||||
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;
|
||||
|
||||
_isBusy = true;
|
||||
if(IsDirty)
|
||||
{
|
||||
_position = 0;
|
||||
|
@ -44,11 +61,25 @@ namespace BITKit.Sensors
|
|||
sensors = Sensors.Values.Where(IsEnabled).OfType<MonoBehaviour>().ToArray();
|
||||
}
|
||||
|
||||
if(Sensors.Count is 0) return;
|
||||
|
||||
Sensors.ElementAt(_position++).Value.Execute().Forget();
|
||||
if (Sensors.Count is 0)
|
||||
{
|
||||
_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;
|
||||
_isBusy = false;
|
||||
}
|
||||
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.Text;
|
||||
using System.Threading;
|
||||
using BITKit.Sensors.States;
|
||||
using BITKit.StateMachine;
|
||||
using Cysharp.Threading.Tasks;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
|
@ -16,212 +18,38 @@ using UnityEngine.UIElements;
|
|||
|
||||
namespace BITKit.Sensors
|
||||
{
|
||||
public interface ISmartTargetProperty{}
|
||||
public interface ISmartTargetState:IState{}
|
||||
/// <summary>
|
||||
/// 智能目标传感器,根据条件,智能选择目标
|
||||
/// </summary>
|
||||
public class SmartTargetSensor :MonoBehaviour,ISensor,IAction
|
||||
public class SmartTargetSensor :StateBasedMonoBehaviour<ISmartTargetState>,ISensor
|
||||
{
|
||||
/// <summary>
|
||||
/// 自动更新
|
||||
/// </summary>
|
||||
[Header(Constant.Header.Settings)]
|
||||
[SerializeField] private bool autoUpdate;
|
||||
[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();
|
||||
|
||||
[SerializeField] private float radius;
|
||||
[SerializeField] private RangeSensor rangeSensor;
|
||||
[SerializeField] private AudioSensor audioSensor;
|
||||
public int Id { get; set; }
|
||||
private readonly CacheList<Transform> _detected=new();
|
||||
private void OnEnable()
|
||||
{
|
||||
SensorQueue.Register(Id=GetInstanceID(),this);
|
||||
Id = GetInstanceID();
|
||||
SensorQueue.Register(Id,this);
|
||||
}
|
||||
private void Start()
|
||||
{
|
||||
TransitionState<Idle>();
|
||||
}
|
||||
private void OnDisable()
|
||||
{
|
||||
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
|
||||
{
|
||||
_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;
|
||||
}
|
||||
CurrentState?.OnStateUpdate(delta);
|
||||
return UniTask.CompletedTask;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
public int Id => _id is 0 ? _id = GetInstanceID() : _id;
|
||||
private int _id;
|
||||
|
||||
public IEnumerable<Transform> Get()
|
||||
{
|
||||
|
@ -89,13 +91,11 @@ namespace BITKit.Sensors
|
|||
if (ignores.Contains(detectedObject)) return false;
|
||||
return !detectedLayer.Allow || detectedLayer.Value.Includes(_collider.gameObject.layer);
|
||||
}
|
||||
|
||||
public float GetDistance()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public UniTask Execute()=>
|
||||
public UniTask Execute(float delta = 0)=>
|
||||
UniTask.CompletedTask;
|
||||
|
||||
private void Update()
|
||||
|
|
|
@ -13,7 +13,8 @@ namespace BITKit
|
|||
[SerializeField] private string[] tags;
|
||||
[Tooltip("Disable when tags is not empty")]
|
||||
[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;
|
||||
private string[] CacheTags;
|
||||
public void SetTags(IReference[] newReference)
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace BITKit
|
|||
{
|
||||
await UniTask.SwitchToMainThread();
|
||||
#if UNITY_EDITOR
|
||||
if (EditorApplication.isPlaying is false)
|
||||
if (EditorApplication.isPlaying is false || EditorApplication.isPaused)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 67732f32069d3bb4ca436ef8de5710e2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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:
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 00511c331928b714d919870827a5c326
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: c23b988a0ca3904468edef1bd026f977
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -0,0 +1,8 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 614549820bd3c514eaf369e4895d1ef0
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
|
@ -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:
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
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)
|
||||
{
|
||||
var radialProgress = visualElement.Q<RadialProgress>();
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace BITKit.IData
|
|||
if(attribute != null)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -111,11 +111,22 @@ namespace BITKit.IData
|
|||
}
|
||||
public sealed class UXStringBinder:UXDataBinder<string>
|
||||
{
|
||||
protected override VisualElement OnCreateUI() => new TextField()
|
||||
protected override VisualElement OnCreateUI()
|
||||
{
|
||||
isDelayed = true,
|
||||
multiline = true
|
||||
};
|
||||
if (this.fieldInfo.GetCustomAttribute<ReadOnlyAttribute>() is not null)
|
||||
{
|
||||
return new Label();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new TextField()
|
||||
{
|
||||
isDelayed = true,
|
||||
multiline = true
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public sealed class UXFloat3Binder:UXDataBinder<float3>
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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 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)
|
||||
BIT4Log.LogException(new NullReferenceException($"未找到{bindPathAtt.Path}"));
|
||||
fieldInfo.SetValue(self,ve);
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace BITKit
|
|||
{
|
||||
var obj = self.serializedObject.targetObject;
|
||||
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)
|
||||
{
|
||||
throw new NullReferenceException($"Field {self.propertyPath} is null");
|
||||
|
@ -51,7 +51,6 @@ namespace BITKit
|
|||
public static void FillDefaultInspector(VisualElement container, SerializedObject serializedObject, bool hideScript)
|
||||
{
|
||||
container.Clear();
|
||||
|
||||
if (serializedObject.targetObject is null)
|
||||
{
|
||||
var label = container.Create<Label>();
|
||||
|
@ -70,7 +69,7 @@ namespace BITKit
|
|||
|
||||
var type = serializedObject.targetObject.GetType();
|
||||
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 _container = container.Create<VisualElement>();
|
||||
|
@ -92,16 +91,60 @@ namespace BITKit
|
|||
{
|
||||
//var label = container.Create<Label>();
|
||||
//label.text =$"propertyPath:{property.propertyPath} fieldInfo:{fieldInfo} type:{type} fieldInfo:{fieldInfo}";
|
||||
var _container = container;
|
||||
|
||||
var field = new PropertyField(property)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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
|
||||
// {
|
||||
|
@ -123,7 +166,10 @@ namespace BITKit
|
|||
{
|
||||
if (method.GetCustomAttribute<BITAttribute>() is null) 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
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
@ -20,11 +21,13 @@ namespace BITKit
|
|||
private static VFXService sinleton;
|
||||
public VFX[] vfxs;
|
||||
private readonly Dictionary<string, UnityPool<Transform>> pools = new();
|
||||
private readonly ConcurrentDictionary<int, Transform> cache = new();
|
||||
|
||||
[SerializeField] private bool debug;
|
||||
[SerializeField] private Optional<int> defaultCapacity;
|
||||
private void Awake()
|
||||
{
|
||||
cache.Clear();
|
||||
sinleton = this;
|
||||
DI.Register(this);
|
||||
}
|
||||
|
@ -68,16 +71,22 @@ namespace BITKit
|
|||
|
||||
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;
|
||||
return true;
|
||||
if (vfx.IsMatch(key))
|
||||
{
|
||||
var x = vfx.prefab;
|
||||
return x;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -59,6 +59,7 @@ namespace BITKit.Vehicles
|
|||
private bool isBraking;
|
||||
private readonly ValidHandle highSpeedHandle = new();
|
||||
private IUnityEntity _unityEntity;
|
||||
public Rigidbody Rigidbody => rigidbody;
|
||||
|
||||
[Inject(true)]
|
||||
private IHealth _health;
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
"GUID:d525ad6bd40672747bde77962f1c401e",
|
||||
"GUID:49b49c76ee64f6b41bf28ef951cb0e50",
|
||||
"GUID:e34a5702dd353724aa315fb8011f08c3",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23"
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:045a42f233e479d41adc32d02b99631e"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
|
|
|
@ -13,7 +13,8 @@ namespace BITKit.OpenWorld
|
|||
[SerializeField,ReadOnly] private int id;
|
||||
[SerializeField] protected Vector3 size = Vector3.one;
|
||||
[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 void QuadTree_Root_Initialized(IQuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>> root)
|
||||
{
|
||||
|
@ -30,6 +31,7 @@ namespace BITKit.OpenWorld
|
|||
}
|
||||
protected virtual void Start()
|
||||
{
|
||||
_bounds= new Bounds(transform.position+transform.rotation * offset,transform.rotation * size);
|
||||
UnityWorldChunkService.Singleton.Register(this);
|
||||
destroyCancellationToken.Register(Dispose);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,17 @@ namespace BITKit.OpenWorld
|
|||
[SerializeField] private ChunkBehaviour chunkBehaviour;
|
||||
private void Start()
|
||||
{
|
||||
chunkBehaviour.OnLodChangedEvent += OnLodChanged;
|
||||
if(colliders is {Length:0})colliders = GetComponentsInChildren<Collider>();
|
||||
try
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -30,22 +39,28 @@ namespace BITKit.OpenWorld
|
|||
{
|
||||
x.enabled = enabledCollider;
|
||||
}
|
||||
catch (UnassignedReferenceException)
|
||||
{
|
||||
GetCollidersInChildren();
|
||||
OnLodChanged(arg1, arg2);
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.Warning<ColliderChunkObject>(gameObject.name);
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
#if UNITY_EDITOR
|
||||
[BIT]
|
||||
private void GetCollidersInChildren()
|
||||
{
|
||||
colliders = GetComponentsInChildren<Collider>();
|
||||
#if UNITY_EDITOR
|
||||
EditorUtility.SetDirty(this);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,11 @@ using System;
|
|||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using BITKit.SceneManagement;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Quadtree;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Pool;
|
||||
|
||||
|
||||
namespace BITKit.OpenWorld
|
||||
|
@ -21,13 +24,16 @@ namespace BITKit.OpenWorld
|
|||
private readonly ConcurrentDictionary<int, IWorldChunkObject> dictionary=new();
|
||||
|
||||
[SerializeReference, SubclassSelector] private ITicker ticker;
|
||||
[SerializeReference, SubclassSelector] private ISceneService sceneService;
|
||||
[SerializeField, ReadOnly] private int count;
|
||||
[SerializeField, ReadOnly] private int tickTaskCount;
|
||||
[SerializeField] private bool drawBounds;
|
||||
[SerializeField, Range(0, 1024)] private int[] lodDistances;
|
||||
[SerializeField] private Vector3 size;
|
||||
private Camera _camera;
|
||||
private readonly HashSet<int> cacheList = new();
|
||||
|
||||
private readonly Queue<(int, IWorldChunkObject)> lodQueue=new();
|
||||
private bool isBusy;
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Singleton = (T) this;
|
||||
|
@ -35,20 +41,35 @@ namespace BITKit.OpenWorld
|
|||
|
||||
protected virtual void Start()
|
||||
{
|
||||
sceneService?.RegisterLoadTaskAsync(LoadTask);
|
||||
ticker.Add(OnTick);
|
||||
destroyCancellationToken.Register(Dispose);
|
||||
_quadtree = new QuadtreeRoot<IWorldChunkObject, Node<IWorldChunkObject>>(transform.position, size);
|
||||
_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);
|
||||
_registerQueue.Clear();
|
||||
_unregisterQueue.Clear();
|
||||
}
|
||||
protected virtual void OnTick(float deltaTime)
|
||||
protected virtual async void OnTick(float deltaTime)
|
||||
{
|
||||
if (!enabled) return;
|
||||
if (isBusy) return;
|
||||
|
||||
isBusy = true;
|
||||
while (_unregisterQueue.TryDequeue(out var obj))
|
||||
{
|
||||
_quadtree.Remove(obj);
|
||||
|
@ -63,28 +84,76 @@ namespace BITKit.OpenWorld
|
|||
}
|
||||
|
||||
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];
|
||||
foreach (var chunkObject in _quadtree.Find(new Bounds(cameraPosition, Vector3.one * distance)))
|
||||
if (cycle++ > 64)
|
||||
{
|
||||
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);
|
||||
}
|
||||
cycle = 0;
|
||||
await UniTask.NextFrame();
|
||||
if (destroyCancellationToken.IsCancellationRequested) return;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
private void OnDrawGizmosSelected()
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace BITKit.OpenWorld
|
|||
if (_sceneHandle is not null) return;
|
||||
var stopWatcher = new System.Diagnostics.Stopwatch();
|
||||
stopWatcher.Start();
|
||||
_sceneHandle = YooAssets.LoadSceneAsync(sceneName.Value,LoadSceneMode.Additive,suspendLoad:true,priority:8);
|
||||
_sceneHandle = YooAssets.LoadSceneAsync(sceneName.Value,LoadSceneMode.Additive,priority:8);
|
||||
await _sceneHandle;
|
||||
stopWatcher.Stop();
|
||||
Debug.Log($"加载场景 {sceneName.Value} 耗时 {stopWatcher.ElapsedMilliseconds}ms");
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace BITKit.GameEditor
|
|||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace BITKit.GameEditor
|
|||
protected readonly List<T> List=new();
|
||||
|
||||
private ListView _listView;
|
||||
private VisualElement _container;
|
||||
protected VisualElement _container { get; private set; }
|
||||
private Button _createButton;
|
||||
|
||||
private void OnEnable()
|
||||
|
@ -99,7 +99,7 @@ namespace BITKit.GameEditor
|
|||
$"{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 serializedObject = new SerializedObject(selected);
|
||||
|
@ -167,6 +167,7 @@ namespace BITKit.GameEditor
|
|||
).ToArray();
|
||||
List.AddRange(allItem.Cast<T>());
|
||||
}
|
||||
|
||||
protected virtual void CreateScriptableObject(string name)
|
||||
{
|
||||
if (string.IsNullOrEmpty(name))
|
||||
|
@ -178,6 +179,8 @@ namespace BITKit.GameEditor
|
|||
|
||||
if (EditorUtility.DisplayDialog("创建", $"是否创建{name}与{path}?", "是", "否") is false) return;
|
||||
|
||||
new DirectoryInfo(Path.GetDirectoryName(path)!).Create();
|
||||
|
||||
var item = CreateInstance<T>();
|
||||
item.name = name;
|
||||
AssetDatabase.CreateAsset(item, path);
|
||||
|
|
|
@ -3,7 +3,9 @@ using System.Collections;
|
|||
using System.Collections.Generic;
|
||||
using MeshCombineStudio;
|
||||
using NGS.AdvancedCullingSystem.Dynamic;
|
||||
using UnityEditor.Build;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Events;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
@ -12,15 +14,21 @@ namespace BITKit.OpenWorld
|
|||
public class OpenWorldCombiner : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private MeshCombiner meshCombiner;
|
||||
|
||||
[SerializeField] private UnityEvent onCombiningReady;
|
||||
|
||||
[SerializeField]
|
||||
private bool allowCullingSource = true;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
meshCombiner.onCombiningReady +=x=> onCombiningReady.Invoke();
|
||||
meshCombiner.onCombiningReady += AddCullingSource;
|
||||
}
|
||||
|
||||
private void AddCullingSource(MeshCombiner meshcombiner)
|
||||
{
|
||||
if (enabled)
|
||||
if (allowCullingSource)
|
||||
AddCullingSource();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,20 +12,35 @@ namespace BITKit
|
|||
public string questName;
|
||||
public string qeustDescription;
|
||||
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()
|
||||
{
|
||||
var quest = QuestSystem.Create(questName, qeustDescription);
|
||||
if (output.isDefined)
|
||||
output.SetValue(quest);
|
||||
EndAction();
|
||||
}
|
||||
protected override void OnStop(bool interrupted)
|
||||
{
|
||||
base.OnStop(interrupted);
|
||||
if (!interrupted) return;
|
||||
if (QuestSystem.quests.TryGetValue(output.value, out var info) &&
|
||||
info.State == QuestSystem.State.InProcess)
|
||||
QuestSystem.Cancel(output.value);
|
||||
}
|
||||
|
||||
if(isInitiated)return;
|
||||
agent.As<MonoBehaviour>().destroyCancellationToken.Register(Disposed);
|
||||
isInitiated = true;
|
||||
; }
|
||||
// protected override void OnStop(bool interrupted)
|
||||
// {
|
||||
// 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);
|
||||
}
|
||||
|
||||
public void OnEntryOverride(bool @override)
|
||||
{
|
||||
_allow.SetDisableElements(this,@override);
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace BITKit.NodeCanvas
|
|||
public BBParameter<Transform> target;
|
||||
protected override void OnExecute()
|
||||
{
|
||||
target.SetValue(sensor.value.CurrentTarget);
|
||||
//target.SetValue(sensor.value.CurrentTarget);
|
||||
EndAction();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue