Newer
Older
DungeonShooting / DungeonShooting_Godot / src / framework / activity / ActivityObject.cs
  1.  
  2. using System;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5. using Config;
  6. using Godot;
  7.  
  8. /// <summary>
  9. /// 房间内活动物体基类, 所有物体都必须继承该类,<br/>
  10. /// 该类提供基础物体运动模拟, 互动接口, 自定义组件, 协程等功能<br/>
  11. /// ActivityObject 子类实例化请不要直接使用 new, 而用该在类上标上 [Tool], 并在 ActivityObject.xlsx 配置文件中注册物体, 导出配置表后使用 ActivityObject.Create(id) 来创建实例.<br/>
  12. /// </summary>
  13. public abstract partial class ActivityObject : CharacterBody2D, IDestroy, ICoroutine
  14. {
  15. /// <summary>
  16. /// 是否是调试模式
  17. /// </summary>
  18. public static bool IsDebug { get; set; }
  19.  
  20. /// <summary>
  21. /// 当前物体对应的配置数据, 如果不是通过 ActivityObject.Create() 函数创建出来的对象那么 ItemConfig 为 null
  22. /// </summary>
  23. public ExcelConfig.ActivityBase ItemConfig { get; private set; }
  24.  
  25. /// <summary>
  26. /// 是否是静态物体, 如果为true, 则会禁用移动处理
  27. /// </summary>
  28. public bool IsStatic
  29. {
  30. get => MoveController != null ? !MoveController.Enable : true;
  31. set
  32. {
  33. if (MoveController != null)
  34. {
  35. MoveController.Enable = !value;
  36. }
  37. }
  38. }
  39.  
  40. /// <summary>
  41. /// 是否显示阴影
  42. /// </summary>
  43. public bool IsShowShadow { get; private set; }
  44. /// <summary>
  45. /// 当前物体显示的阴影图像, 节点名称必须叫 "ShadowSprite", 类型为 Sprite2D
  46. /// </summary>
  47. [Export, ExportFillNode]
  48. public Sprite2D ShadowSprite { get; set; }
  49. /// <summary>
  50. /// 当前物体显示的精灵图像, 节点名称必须叫 "AnimatedSprite2D", 类型为 AnimatedSprite2D
  51. /// </summary>
  52. [Export, ExportFillNode]
  53. public AnimatedSprite2D AnimatedSprite { get; set; }
  54.  
  55. /// <summary>
  56. /// 当前物体碰撞器节点, 节点名称必须叫 "Collision", 类型为 CollisionShape2D
  57. /// </summary>
  58. [Export, ExportFillNode]
  59. public CollisionShape2D Collision { get; set; }
  60.  
  61. /// <summary>
  62. /// 是否调用过 Destroy() 函数
  63. /// </summary>
  64. public bool IsDestroyed { get; private set; }
  65. /// <summary>
  66. /// 阴影偏移
  67. /// </summary>
  68. public Vector2 ShadowOffset { get; protected set; } = new Vector2(0, 2);
  69. /// <summary>
  70. /// 移动控制器
  71. /// </summary>
  72. public MoveController MoveController { get; private set; }
  73.  
  74. /// <summary>
  75. /// 物体移动基础速率
  76. /// </summary>
  77. public Vector2 BasisVelocity
  78. {
  79. get
  80. {
  81. if (MoveController != null)
  82. {
  83. return MoveController.BasisVelocity;
  84. }
  85.  
  86. return Vector2.Zero;
  87. }
  88. set
  89. {
  90. if (MoveController != null)
  91. {
  92. MoveController.BasisVelocity = value;
  93. }
  94. }
  95. }
  96.  
  97. /// <summary>
  98. /// 当前物体归属的区域, 如果为 null 代表不属于任何一个区域
  99. /// </summary>
  100. public AffiliationArea AffiliationArea
  101. {
  102. get => _affiliationArea;
  103. set
  104. {
  105. if (value != _affiliationArea)
  106. {
  107. var prev = _affiliationArea;
  108. _affiliationArea = value;
  109. if (!IsDestroyed)
  110. {
  111. OnAffiliationChange(prev);
  112. }
  113. }
  114. }
  115. }
  116.  
  117. /// <summary>
  118. /// 是否正在投抛过程中
  119. /// </summary>
  120. public bool IsThrowing => _throwForce != null && !_isFallOver;
  121.  
  122. /// <summary>
  123. /// 当前物体的海拔高度, 如果大于0, 则会做自由落体运动, 也就是执行投抛逻辑
  124. /// </summary>
  125. public float Altitude
  126. {
  127. get => _altitude;
  128. set
  129. {
  130. _altitude = value;
  131. _hasResilienceVerticalSpeed = false;
  132. }
  133. }
  134.  
  135. private float _altitude = 0;
  136.  
  137. /// <summary>
  138. /// 物体纵轴移动速度, 如果设置大于0, 就可以营造向上投抛物体的效果, 该值会随着重力加速度衰减
  139. /// </summary>
  140. public float VerticalSpeed
  141. {
  142. get => _verticalSpeed;
  143. set
  144. {
  145. _verticalSpeed = value;
  146. _hasResilienceVerticalSpeed = false;
  147. }
  148. }
  149.  
  150. private float _verticalSpeed;
  151.  
  152. /// <summary>
  153. /// 投抛状态下物体碰撞器大小, 如果 (x, y) 都小于 0, 则默认使用 AnimatedSprite 的默认动画第一帧的大小
  154. /// </summary>
  155. [Export]
  156. public Vector2 ThrowCollisionSize { get; set; } = new Vector2(-1, -1);
  157.  
  158. /// <summary>
  159. /// 是否启用垂直方向上的运动模拟, 默认开启, 如果禁用, 那么下落和投抛效果, 同样 Throw() 函数也将失效
  160. /// </summary>
  161. public bool EnableVerticalMotion { get; set; } = true;
  162.  
  163. /// <summary>
  164. /// 撞到墙壁反弹时是否锁定旋转角度, 如果为 false, 则反弹后将直接修改旋转角度
  165. /// </summary>
  166. public bool BounceLockRotation { get; set; } = true;
  167. /// <summary>
  168. /// 是否启用物体更新行为, 默认 true, 如果禁用, 则会停止当前物体的 Process(), PhysicsProcess() 调用, 并且禁用 Collision 节点, 禁用后所有组件也同样被禁用行为
  169. /// </summary>
  170. public bool EnableBehavior
  171. {
  172. get => _enableBehavior;
  173. set
  174. {
  175. if (value != _enableBehavior)
  176. {
  177. _enableBehavior = value;
  178. SetProcess(value);
  179. SetPhysicsProcess(value);
  180. if (value)
  181. {
  182. Collision.Disabled = _enableBehaviorCollisionDisabledFlag;
  183. }
  184. else
  185. {
  186. _enableBehaviorCollisionDisabledFlag = Collision.Disabled;
  187. Collision.Disabled = true;
  188. }
  189. }
  190. }
  191. }
  192.  
  193. /// <summary>
  194. /// 是否启用自定义行为, 默认 true, 如果禁用, 则会停止调用子类重写的 Process(), PhysicsProcess() 函数, 并且当前物体除 MoveController 以外的组件 Process(), PhysicsProcess() 也会停止调用
  195. /// </summary>
  196. public bool EnableCustomBehavior { get; set; } = true;
  197. /// <summary>
  198. /// 物体材质数据
  199. /// </summary>
  200. public ExcelConfig.ActivityMaterial ActivityMaterial { get; private set; }
  201. /// <summary>
  202. /// 所在的 World 对象
  203. /// </summary>
  204. public World World { get; private set; }
  205.  
  206. /// <summary>
  207. /// 是否开启描边
  208. /// </summary>
  209. public bool ShowOutline
  210. {
  211. get => _showOutline;
  212. set
  213. {
  214. if (_blendShaderMaterial != null)
  215. {
  216. if (value != _showOutline)
  217. {
  218. _blendShaderMaterial.SetShaderParameter("show_outline", value);
  219. if (_shadowBlendShaderMaterial != null)
  220. {
  221. _shadowBlendShaderMaterial.SetShaderParameter("show_outline", value);
  222. }
  223. _showOutline = value;
  224. }
  225. }
  226. }
  227. }
  228.  
  229. /// <summary>
  230. /// 描边颜色
  231. /// </summary>
  232. public Color OutlineColor
  233. {
  234. get
  235. {
  236. if (!_initOutlineColor)
  237. {
  238. _initOutlineColor = true;
  239. if (_blendShaderMaterial != null)
  240. {
  241. _outlineColor = _blendShaderMaterial.GetShaderParameter("outline_color").AsColor();
  242. }
  243. }
  244.  
  245. return _outlineColor;
  246. }
  247. set
  248. {
  249. _initOutlineColor = true;
  250. if (value != _outlineColor)
  251. {
  252. _blendShaderMaterial.SetShaderParameter("outline_color", value);
  253. }
  254.  
  255. _outlineColor = value;
  256. }
  257. }
  258.  
  259. // --------------------------------------------------------------------------------
  260.  
  261. //是否正在调用组件 Update 函数
  262. private bool _updatingComp = false;
  263. //组件集合
  264. private readonly List<KeyValuePair<Type, Component>> _components = new List<KeyValuePair<Type, Component>>();
  265. //修改的组件集合, value 为 true 表示添加组件, false 表示移除组件
  266. private readonly List<KeyValuePair<Component, bool>> _changeComponents = new List<KeyValuePair<Component, bool>>();
  267. //上一帧动画名称
  268. private string _prevAnimation;
  269. //上一帧动画
  270. private int _prevAnimationFrame;
  271.  
  272. //播放 Hit 动画
  273. private bool _playHit;
  274. private float _playHitSchedule;
  275.  
  276. //混色shader材质
  277. private ShaderMaterial _blendShaderMaterial;
  278. private ShaderMaterial _shadowBlendShaderMaterial;
  279. //存储投抛该物体时所产生的数据
  280. private readonly ActivityFallData _fallData = new ActivityFallData();
  281. //所在层级
  282. private RoomLayerEnum _currLayer;
  283. //标记字典
  284. private Dictionary<string, object> _signMap;
  285. //开启的协程
  286. private List<CoroutineData> _coroutineList;
  287.  
  288. //物体所在区域
  289. private AffiliationArea _affiliationArea;
  290.  
  291. //是否是第一次下坠
  292. private bool _firstFall = true;
  293. //下坠是否已经结束
  294. private bool _isFallOver = true;
  295.  
  296. //下坠状态碰撞器形状
  297. private RectangleShape2D _throwRectangleShape;
  298.  
  299. //投抛移动速率
  300. private ExternalForce _throwForce;
  301. //落到地上回弹的速度
  302. private float _resilienceVerticalSpeed = 0;
  303. private bool _hasResilienceVerticalSpeed = false;
  304.  
  305. //是否启用物体行为
  306. private bool _enableBehavior = true;
  307. private bool _enableBehaviorCollisionDisabledFlag;
  308.  
  309. private bool _processingBecomesStaticImage = false;
  310.  
  311. // --------------------------------------------------------------------------------
  312. //实例索引
  313. private static long _instanceIndex = 0;
  314.  
  315. //是否启用描边
  316. private bool _showOutline = false;
  317. //描边颜色
  318. private bool _initOutlineColor = false;
  319. private Color _outlineColor = new Color(0, 0, 0, 1);
  320. //冻结显示的Sprite
  321. private FreezeSprite _freezeSprite;
  322.  
  323. //初始化节点
  324. private void _InitNode(ExcelConfig.ActivityBase config, World world)
  325. {
  326. #if TOOLS
  327. if (!Engine.IsEditorHint())
  328. {
  329. if (GetType().GetCustomAttributes(typeof(ToolAttribute), false).Length == 0)
  330. {
  331. throw new Exception($"ActivityObject子类'{GetType().FullName}'没有加[Tool]标记!");
  332. }
  333. }
  334. #endif
  335. if (config.Material == null)
  336. {
  337. ActivityMaterial = ExcelConfig.ActivityMaterial_List[0];
  338. }
  339. else
  340. {
  341. ActivityMaterial = config.Material;
  342. }
  343. World = world;
  344. ItemConfig = config;
  345. Name = GetType().Name + (_instanceIndex++);
  346. _blendShaderMaterial = AnimatedSprite.Material as ShaderMaterial;
  347. _shadowBlendShaderMaterial = ShadowSprite.Material as ShaderMaterial;
  348. if (_blendShaderMaterial != null)
  349. {
  350. _showOutline = _blendShaderMaterial.GetShaderParameter("show_outline").AsBool();
  351. }
  352.  
  353. if (_shadowBlendShaderMaterial != null)
  354. {
  355. _shadowBlendShaderMaterial.SetShaderParameter("show_outline", _showOutline);
  356. }
  357.  
  358. ShadowSprite.Visible = false;
  359. MotionMode = MotionModeEnum.Floating;
  360. MoveController = AddComponent<MoveController>();
  361. IsStatic = config.IsStatic;
  362. OnInit();
  363. }
  364.  
  365. /// <summary>
  366. /// 子类重写的 _Ready() 可能会比 _InitNode() 函数调用晚, 所以禁止子类重写, 如需要 _Ready() 类似的功能需重写 OnInit()
  367. /// </summary>
  368. public sealed override void _Ready()
  369. {
  370.  
  371. }
  372. /// <summary>
  373. /// 子类需要重写 _EnterTree() 函数, 请重写 EnterTree()
  374. /// </summary>
  375. public sealed override void _EnterTree()
  376. {
  377. #if TOOLS
  378. // 在工具模式下创建的 template 节点自动创建对应的必要子节点
  379. if (Engine.IsEditorHint())
  380. {
  381. _InitNodeInEditor();
  382. return;
  383. }
  384. #endif
  385. EnterTree();
  386. }
  387. /// <summary>
  388. /// 子类需要重写 _ExitTree() 函数, 请重写 ExitTree()
  389. /// </summary>
  390. public sealed override void _ExitTree()
  391. {
  392. #if TOOLS
  393. // 在工具模式下创建的 template 节点自动创建对应的必要子节点
  394. if (Engine.IsEditorHint())
  395. {
  396. return;
  397. }
  398. #endif
  399. ExitTree();
  400. }
  401.  
  402. /// <summary>
  403. /// 显示并更新阴影
  404. /// </summary>
  405. public void ShowShadowSprite()
  406. {
  407. var anim = AnimatedSprite.Animation;
  408. var frame = AnimatedSprite.Frame;
  409. if (_prevAnimation != anim || _prevAnimationFrame != frame)
  410. {
  411. var frames = AnimatedSprite.SpriteFrames;
  412. if (frames != null && frames.HasAnimation(anim))
  413. {
  414. //切换阴影动画
  415. ShadowSprite.Texture = frames.GetFrameTexture(anim, frame);
  416. }
  417. }
  418.  
  419. _prevAnimation = anim;
  420. _prevAnimationFrame = frame;
  421.  
  422. IsShowShadow = true;
  423. CalcShadowTransform();
  424. ShadowSprite.Visible = true;
  425. }
  426.  
  427. /// <summary>
  428. /// 隐藏阴影
  429. /// </summary>
  430. public void HideShadowSprite()
  431. {
  432. ShadowSprite.Visible = false;
  433. IsShowShadow = false;
  434. }
  435.  
  436. /// <summary>
  437. /// 设置默认序列帧动画的第一帧
  438. /// </summary>
  439. public void SetDefaultTexture(Texture2D texture)
  440. {
  441. if (AnimatedSprite.SpriteFrames == null)
  442. {
  443. SpriteFrames spriteFrames = new SpriteFrames();
  444. AnimatedSprite.SpriteFrames = spriteFrames;
  445. spriteFrames.AddFrame("default", texture);
  446. }
  447. else
  448. {
  449. SpriteFrames spriteFrames = AnimatedSprite.SpriteFrames;
  450. spriteFrames.SetFrame("default", 0, texture);
  451. }
  452. AnimatedSprite.Play("default");
  453. }
  454.  
  455. /// <summary>
  456. /// 获取默认序列帧动画的第一帧
  457. /// </summary>
  458. public Texture2D GetDefaultTexture()
  459. {
  460. return AnimatedSprite.SpriteFrames.GetFrameTexture("default", 0);
  461. }
  462. /// <summary>
  463. /// 获取当前序列帧动画的 Texture2D
  464. /// </summary>
  465. public Texture2D GetCurrentTexture()
  466. {
  467. var spriteFrames = AnimatedSprite.SpriteFrames;
  468. if (spriteFrames == null)
  469. {
  470. return null;
  471. }
  472. return spriteFrames.GetFrameTexture(AnimatedSprite.Animation, AnimatedSprite.Frame);
  473. }
  474.  
  475. /// <summary>
  476. /// 物体初始化时调用
  477. /// </summary>
  478. public virtual void OnInit()
  479. {
  480. }
  481. /// <summary>
  482. /// 进入场景树时调用
  483. /// </summary>
  484. public virtual void EnterTree()
  485. {
  486. }
  487.  
  488. /// <summary>
  489. /// 离开场景树时调用
  490. /// </summary>
  491. public virtual void ExitTree()
  492. {
  493. }
  494. /// <summary>
  495. /// 返回是否能与其他ActivityObject互动
  496. /// </summary>
  497. /// <param name="master">触发者</param>
  498. public virtual CheckInteractiveResult CheckInteractive(ActivityObject master)
  499. {
  500. return new CheckInteractiveResult(this);
  501. }
  502.  
  503. /// <summary>
  504. /// 与其它ActivityObject互动时调用, 如果要检测是否能互动请 CheckInteractive() 函数, 如果直接调用该函数那么属于强制互动行为, 例如子弹碰到物体
  505. /// </summary>
  506. /// <param name="master">触发者</param>
  507. public virtual void Interactive(ActivityObject master)
  508. {
  509. }
  510.  
  511. /// <summary>
  512. /// 开始投抛该物体时调用
  513. /// </summary>
  514. protected virtual void OnThrowStart()
  515. {
  516. }
  517. /// <summary>
  518. /// 投抛该物体达到最高点时调用
  519. /// </summary>
  520. protected virtual void OnThrowMaxHeight(float height)
  521. {
  522. }
  523.  
  524. /// <summary>
  525. /// 投抛状态下第一次接触地面时调用, 之后的回弹落地将不会调用该函数
  526. /// </summary>
  527. protected virtual void OnFirstFallToGround()
  528. {
  529. }
  530.  
  531. /// <summary>
  532. /// 投抛状态下每次接触地面时调用
  533. /// </summary>
  534. protected virtual void OnFallToGround()
  535. {
  536. }
  537.  
  538. /// <summary>
  539. /// 投抛结束时调用
  540. /// </summary>
  541. protected virtual void OnThrowOver()
  542. {
  543. }
  544.  
  545. /// <summary>
  546. /// 当前物体销毁时调用, 销毁物体请调用 Destroy() 函数
  547. /// </summary>
  548. protected virtual void OnDestroy()
  549. {
  550. }
  551.  
  552. /// <summary>
  553. /// 每帧调用一次, 物体的 Process() 会在组件的 Process() 之前调用
  554. /// </summary>
  555. protected virtual void Process(float delta)
  556. {
  557. }
  558. /// <summary>
  559. /// 每物理帧调用一次, 物体的 PhysicsProcess() 会在组件的 PhysicsProcess() 之前调用
  560. /// </summary>
  561. protected virtual void PhysicsProcess(float delta)
  562. {
  563. }
  564. /// <summary>
  565. /// 如果开启 debug, 则每帧调用该函数, 可用于绘制文字线段等
  566. /// </summary>
  567. protected virtual void DebugDraw()
  568. {
  569. }
  570.  
  571. /// <summary>
  572. /// 归属区域发生改变
  573. /// </summary>
  574. /// <param name="prevArea">上一个区域, 注意可能为空</param>
  575. protected virtual void OnAffiliationChange(AffiliationArea prevArea)
  576. {
  577. }
  578.  
  579. /// <summary>
  580. /// 移动并碰撞到物体时调用该函数, 参数为碰撞数据, 该函数由 MoveController 调用
  581. /// </summary>
  582. public virtual void OnMoveCollision(KinematicCollision2D collision)
  583. {
  584. }
  585.  
  586. /// <summary>
  587. /// 撞到墙壁反弹时调用该函数, 参数为反弹的角度, 弧度制, 该函数由 MoveController 调用
  588. /// </summary>
  589. public virtual void OnBounce(float rotation)
  590. {
  591. }
  592.  
  593. /// <summary>
  594. /// 返回当物体 CollisionLayer 是否能与 mask 层碰撞
  595. /// </summary>
  596. public bool CollisionWithMask(uint mask)
  597. {
  598. return (CollisionLayer & mask) != 0;
  599. }
  600. /// <summary>
  601. /// 拾起一个 node 节点, 也就是将其从场景树中移除
  602. /// </summary>
  603. public void Pickup()
  604. {
  605. var parent = GetParent();
  606. if (parent != null)
  607. {
  608. if (IsThrowing)
  609. {
  610. StopThrow();
  611. }
  612.  
  613. parent.RemoveChild(this);
  614. }
  615. }
  616.  
  617. /// <summary>
  618. /// 将一个节点扔到地上
  619. /// <param name="layer">放入的层</param>
  620. /// <param name="showShadow">是否显示阴影</param>
  621. /// </summary>
  622. public virtual void PutDown(RoomLayerEnum layer, bool showShadow = true)
  623. {
  624. _currLayer = layer;
  625. var parent = GetParent();
  626. var root = GameApplication.Instance.World.GetRoomLayer(layer);
  627. if (parent != root)
  628. {
  629. if (parent != null)
  630. {
  631. Reparent(root);
  632. }
  633. else
  634. {
  635. root.AddChild(this);
  636. }
  637. }
  638.  
  639. if (showShadow)
  640. {
  641. if (IsInsideTree())
  642. {
  643. ShowShadowSprite();
  644. }
  645. else
  646. {
  647. //注意需要延时调用
  648. CallDeferred(nameof(ShowShadowSprite));
  649. CalcShadowTransform();
  650. }
  651. }
  652. else
  653. {
  654. ShadowSprite.Visible = false;
  655. }
  656. }
  657.  
  658. /// <summary>
  659. /// 将一个节点扔到地上
  660. /// </summary>
  661. /// <param name="position">放置的位置</param>
  662. /// <param name="layer">放入的层</param>
  663. /// <param name="showShadow">是否显示阴影</param>
  664. public void PutDown(Vector2 position, RoomLayerEnum layer, bool showShadow = true)
  665. {
  666. PutDown(layer);
  667. Position = position;
  668. }
  669.  
  670. /// <summary>
  671. /// 将该节点投抛出去
  672. /// </summary>
  673. /// <param name="altitude">初始高度</param>
  674. /// <param name="verticalSpeed">纵轴速度</param>
  675. /// <param name="velocity">移动速率</param>
  676. /// <param name="rotateSpeed">旋转速度</param>
  677. public void Throw(float altitude, float verticalSpeed, Vector2 velocity, float rotateSpeed)
  678. {
  679. var parent = GetParent();
  680. if (parent == null)
  681. {
  682. GameApplication.Instance.World.YSortLayer.AddChild(this);
  683. }
  684. else if (parent != GameApplication.Instance.World.YSortLayer)
  685. {
  686. parent.RemoveChild(this);
  687. GameApplication.Instance.World.YSortLayer.AddChild(this);
  688. }
  689. Altitude = altitude;
  690. //Position = Position + new Vector2(0, altitude);
  691. VerticalSpeed = verticalSpeed;
  692. //ThrowRotationDegreesSpeed = rotateSpeed;
  693. if (_throwForce != null)
  694. {
  695. MoveController.RemoveForce(_throwForce);
  696. }
  697.  
  698. _throwForce = new ExternalForce(ForceNames.Throw);
  699. _throwForce.Velocity = velocity;
  700. _throwForce.RotationSpeed = Mathf.DegToRad(rotateSpeed);
  701. MoveController.AddForce(_throwForce);
  702.  
  703. InitThrowData();
  704. }
  705.  
  706. /// <summary>
  707. /// 将该节点投抛出去
  708. /// </summary>
  709. /// <param name="position">初始位置</param>
  710. /// <param name="altitude">初始高度</param>
  711. /// <param name="verticalSpeed">纵轴速度</param>
  712. /// <param name="velocity">移动速率</param>
  713. /// <param name="rotateSpeed">旋转速度</param>
  714. public void Throw(Vector2 position, float altitude, float verticalSpeed, Vector2 velocity, float rotateSpeed)
  715. {
  716. GlobalPosition = position;
  717. Throw(altitude, verticalSpeed, velocity, rotateSpeed);
  718. }
  719.  
  720.  
  721. /// <summary>
  722. /// 强制停止投抛运动
  723. /// </summary>
  724. public void StopThrow()
  725. {
  726. _isFallOver = true;
  727. RestoreCollision();
  728. }
  729.  
  730. /// <summary>
  731. /// 往当前物体上挂载一个组件
  732. /// </summary>
  733. public T AddComponent<T>() where T : Component, new()
  734. {
  735. var component = new T();
  736. if (_updatingComp)
  737. {
  738. _changeComponents.Add(new KeyValuePair<Component, bool>(component, true));
  739. }
  740. else
  741. {
  742. _components.Add(new KeyValuePair<Type, Component>(typeof(T), component));
  743. }
  744.  
  745. component.Master = this;
  746. component.Ready();
  747. component.OnEnable();
  748. return component;
  749. }
  750.  
  751. /// <summary>
  752. /// 往当前物体上挂载一个组件
  753. /// </summary>
  754. public Component AddComponent(Type type)
  755. {
  756. var component = (Component)Activator.CreateInstance(type);
  757. if (_updatingComp)
  758. {
  759. _changeComponents.Add(new KeyValuePair<Component, bool>(component, true));
  760. }
  761. else
  762. {
  763. _components.Add(new KeyValuePair<Type, Component>(type, component));
  764. }
  765. component.Master = this;
  766. component.Ready();
  767. component.OnEnable();
  768. return component;
  769. }
  770.  
  771. /// <summary>
  772. /// 移除一个组件, 并且销毁
  773. /// </summary>
  774. /// <param name="component">组件对象</param>
  775. public void RemoveComponent(Component component)
  776. {
  777. if (component.IsDestroyed)
  778. {
  779. return;
  780. }
  781.  
  782. if (_updatingComp)
  783. {
  784. _changeComponents.Add(new KeyValuePair<Component, bool>(component, false));
  785. component.Destroy();
  786. }
  787. else
  788. {
  789. for (var i = 0; i < _components.Count; i++)
  790. {
  791. if (_components[i].Value == component)
  792. {
  793. _components.RemoveAt(i);
  794. component.Destroy();
  795. return;
  796. }
  797. }
  798. }
  799. }
  800.  
  801. /// <summary>
  802. /// 根据类型获取一个组件
  803. /// </summary>
  804. public Component GetComponent(Type type)
  805. {
  806. for (int i = 0; i < _components.Count; i++)
  807. {
  808. var temp = _components[i];
  809. if (temp.Key.IsAssignableTo(type))
  810. {
  811. return temp.Value;
  812. }
  813. }
  814.  
  815. if (_updatingComp)
  816. {
  817. for (var i = 0; i < _changeComponents.Count; i++)
  818. {
  819. var temp = _components[i];
  820. if (temp.Value.GetType().IsAssignableTo(type))
  821. {
  822. return temp.Value;
  823. }
  824. }
  825. }
  826.  
  827. return null;
  828. }
  829.  
  830. /// <summary>
  831. /// 根据类型获取一个组件
  832. /// </summary>
  833. public T GetComponent<T>() where T : Component
  834. {
  835. for (int i = 0; i < _components.Count; i++)
  836. {
  837. var temp = _components[i];
  838. if (temp.Value is T component)
  839. {
  840. return component;
  841. }
  842. }
  843.  
  844. if (_updatingComp)
  845. {
  846. for (var i = 0; i < _changeComponents.Count; i++)
  847. {
  848. var temp = _components[i];
  849. if (temp.Value is T component)
  850. {
  851. return component;
  852. }
  853. }
  854. }
  855.  
  856. return null;
  857. }
  858.  
  859. /// <summary>
  860. /// 根据类型获取所有相同类型的组件
  861. /// </summary>
  862. public Component[] GetComponents(Type type)
  863. {
  864. var list = new List<Component>();
  865. for (int i = 0; i < _components.Count; i++)
  866. {
  867. var temp = _components[i];
  868. if (temp.Key.IsAssignableTo(type))
  869. {
  870. list.Add(temp.Value);
  871. }
  872. }
  873.  
  874. if (_updatingComp)
  875. {
  876. for (var i = 0; i < _changeComponents.Count; i++)
  877. {
  878. var temp = _components[i];
  879. if (temp.Value.GetType().IsAssignableTo(type))
  880. {
  881. list.Add(temp.Value);
  882. }
  883. }
  884. }
  885.  
  886. return list.ToArray();
  887. }
  888. /// <summary>
  889. /// 根据类型获取所有相同类型的组件
  890. /// </summary>
  891. public T[] GetComponents<T>() where T : Component
  892. {
  893. var list = new List<T>();
  894. for (int i = 0; i < _components.Count; i++)
  895. {
  896. var temp = _components[i];
  897. if (temp.Value is T component)
  898. {
  899. list.Add(component);
  900. }
  901. }
  902.  
  903. if (_updatingComp)
  904. {
  905. for (var i = 0; i < _changeComponents.Count; i++)
  906. {
  907. var temp = _components[i];
  908. if (temp.Value is T component)
  909. {
  910. list.Add(component);
  911. }
  912. }
  913. }
  914.  
  915. return list.ToArray();
  916. }
  917. /// <summary>
  918. /// 设置混色材质的颜色
  919. /// </summary>
  920. public void SetBlendColor(Color color)
  921. {
  922. _blendShaderMaterial.SetShaderParameter("blend", color);
  923. }
  924.  
  925. /// <summary>
  926. /// 获取混色材质的颜色
  927. /// </summary>
  928. public Color GetBlendColor()
  929. {
  930. return _blendShaderMaterial.GetShaderParameter("blend").AsColor();
  931. }
  932. /// <summary>
  933. /// 设置混色材质的强度
  934. /// </summary>
  935. public void SetBlendSchedule(float value)
  936. {
  937. _blendShaderMaterial.SetShaderParameter("schedule", value);
  938. }
  939.  
  940. /// <summary>
  941. /// 获取混色材质的强度
  942. /// </summary>
  943. public float GetBlendSchedule()
  944. {
  945. return _blendShaderMaterial.GetShaderParameter("schedule").AsSingle();
  946. }
  947.  
  948. /// <summary>
  949. /// 设置混色颜色
  950. /// </summary>
  951. public void SetBlendModulate(Color color)
  952. {
  953. _blendShaderMaterial.SetShaderParameter("modulate", color);
  954. _shadowBlendShaderMaterial.SetShaderParameter("modulate", color);
  955. }
  956. /// <summary>
  957. /// 获取混色颜色
  958. /// </summary>
  959. public Color SetBlendModulate()
  960. {
  961. return _blendShaderMaterial.GetShaderParameter("modulate").AsColor();
  962. }
  963. /// <summary>
  964. /// 每帧调用一次, 为了防止子类覆盖 _Process(), 给 _Process() 加上了 sealed, 子类需要帧循环函数请重写 Process() 函数
  965. /// </summary>
  966. public sealed override void _Process(double delta)
  967. {
  968. #if TOOLS
  969. if (Engine.IsEditorHint())
  970. {
  971. return;
  972. }
  973. #endif
  974. var newDelta = (float)delta;
  975. if (EnableCustomBehavior)
  976. {
  977. Process(newDelta);
  978. }
  979. //更新组件
  980. if (_components.Count > 0)
  981. {
  982. _updatingComp = true;
  983. if (EnableCustomBehavior) //启用所有组件
  984. {
  985. for (int i = 0; i < _components.Count; i++)
  986. {
  987. if (IsDestroyed) return;
  988. var temp = _components[i].Value;
  989. if (temp != null && temp.Enable)
  990. {
  991. temp.Process(newDelta);
  992. }
  993. }
  994. }
  995. else //只更新 MoveController 组件
  996. {
  997. if (MoveController.Enable)
  998. {
  999. MoveController.Process(newDelta);
  1000. }
  1001. }
  1002. _updatingComp = false;
  1003. if (_changeComponents.Count > 0)
  1004. {
  1005. RefreshComponent();
  1006. }
  1007. }
  1008.  
  1009. // 更新下坠处理逻辑
  1010. UpdateFall(newDelta);
  1011.  
  1012. //阴影
  1013. UpdateShadowSprite(newDelta);
  1014. // Hit 动画
  1015. if (_playHit)
  1016. {
  1017. if (_playHitSchedule < 0.05f)
  1018. {
  1019. _blendShaderMaterial.SetShaderParameter("schedule", 1);
  1020. }
  1021. else if (_playHitSchedule < 0.15f)
  1022. {
  1023. _blendShaderMaterial.SetShaderParameter("schedule", Mathf.Lerp(1, 0, (_playHitSchedule - 0.05f) / 0.1f));
  1024. }
  1025. if (_playHitSchedule >= 0.15f)
  1026. {
  1027. _blendShaderMaterial.SetShaderParameter("schedule", 0);
  1028. _playHitSchedule = 0;
  1029. _playHit = false;
  1030. }
  1031. else
  1032. {
  1033. _playHitSchedule += newDelta;
  1034. }
  1035. }
  1036. //协程更新
  1037. ProxyCoroutineHandler.ProxyUpdateCoroutine(ref _coroutineList, newDelta);
  1038. //调试绘制
  1039. if (IsDebug)
  1040. {
  1041. QueueRedraw();
  1042. }
  1043. }
  1044.  
  1045. /// <summary>
  1046. /// 更新下坠处理逻辑
  1047. /// </summary>
  1048. public void UpdateFall(float delta)
  1049. {
  1050. // 下坠判定
  1051. if (Altitude > 0 || VerticalSpeed != 0)
  1052. {
  1053. if (_isFallOver) // 没有处于下坠状态, 则进入下坠状态
  1054. {
  1055. InitThrowData();
  1056. }
  1057. else
  1058. {
  1059. if (EnableVerticalMotion) //如果启用了纵向运动, 则更新运动
  1060. {
  1061. //GlobalRotationDegrees = GlobalRotationDegrees + ThrowRotationDegreesSpeed * newDelta;
  1062.  
  1063. var ysp = VerticalSpeed;
  1064.  
  1065. _altitude += VerticalSpeed * delta;
  1066. _verticalSpeed -= GameConfig.G * delta;
  1067.  
  1068. //当高度大于16时, 显示在所有物体上
  1069. if (Altitude >= 16)
  1070. {
  1071. AnimatedSprite.ZIndex = 20;
  1072. }
  1073. else
  1074. {
  1075. AnimatedSprite.ZIndex = 0;
  1076. }
  1077. //达到最高点
  1078. if (ysp > 0 && ysp * VerticalSpeed < 0)
  1079. {
  1080. OnThrowMaxHeight(Altitude);
  1081. }
  1082.  
  1083. //落地判断
  1084. if (Altitude <= 0)
  1085. {
  1086. _altitude = 0;
  1087.  
  1088. //第一次接触地面
  1089. if (_firstFall)
  1090. {
  1091. _firstFall = false;
  1092. OnFirstFallToGround();
  1093. }
  1094.  
  1095. if (_throwForce != null)
  1096. {
  1097. //缩放移动速度
  1098. //MoveController.ScaleAllForce(BounceSpeed);
  1099. _throwForce.Velocity *= ActivityMaterial.FallBounceSpeed;
  1100. //缩放旋转速度
  1101. //MoveController.ScaleAllRotationSpeed(BounceStrength);
  1102. _throwForce.RotationSpeed *= ActivityMaterial.FallBounceRotation;
  1103. }
  1104. //如果落地高度不够低, 再抛一次
  1105. if (ActivityMaterial.Bounce && (!_hasResilienceVerticalSpeed || _resilienceVerticalSpeed > 5))
  1106. {
  1107. if (!_hasResilienceVerticalSpeed)
  1108. {
  1109. _hasResilienceVerticalSpeed = true;
  1110. _resilienceVerticalSpeed = -VerticalSpeed * ActivityMaterial.FallBounceStrength;
  1111. }
  1112. else
  1113. {
  1114. if (_resilienceVerticalSpeed < 25)
  1115. {
  1116. _resilienceVerticalSpeed = _resilienceVerticalSpeed * ActivityMaterial.FallBounceStrength * 0.4f;
  1117. }
  1118. else
  1119. {
  1120. _resilienceVerticalSpeed = _resilienceVerticalSpeed * ActivityMaterial.FallBounceStrength;
  1121. }
  1122. }
  1123. _verticalSpeed = _resilienceVerticalSpeed;
  1124. _isFallOver = false;
  1125.  
  1126. OnFallToGround();
  1127. }
  1128. else //结束
  1129. {
  1130. _verticalSpeed = 0;
  1131.  
  1132. if (_throwForce != null)
  1133. {
  1134. MoveController.RemoveForce(_throwForce);
  1135. _throwForce = null;
  1136. }
  1137. _isFallOver = true;
  1138. OnFallToGround();
  1139. ThrowOver();
  1140. }
  1141. }
  1142. }
  1143.  
  1144. //计算精灵位置
  1145. CalcThrowAnimatedPosition();
  1146. }
  1147. }
  1148.  
  1149. }
  1150.  
  1151. /// <summary>
  1152. /// 更新阴影逻辑
  1153. /// </summary>
  1154. public void UpdateShadowSprite(float delta)
  1155. {
  1156. // 阴影
  1157. if (ShadowSprite.Visible)
  1158. {
  1159. //更新阴影贴图, 使其和动画一致
  1160. var anim = AnimatedSprite.Animation;
  1161. var frame = AnimatedSprite.Frame;
  1162. if (_prevAnimation != anim || _prevAnimationFrame != frame)
  1163. {
  1164. //切换阴影动画
  1165. ShadowSprite.Texture = AnimatedSprite.SpriteFrames.GetFrameTexture(anim, AnimatedSprite.Frame);
  1166. }
  1167.  
  1168. _prevAnimation = anim;
  1169. _prevAnimationFrame = frame;
  1170.  
  1171. if (_freezeSprite == null || !_freezeSprite.IsFrozen)
  1172. {
  1173. //计算阴影
  1174. CalcShadowTransform();
  1175. }
  1176. }
  1177.  
  1178. }
  1179. /// <summary>
  1180. /// 每物理帧调用一次, 为了防止子类覆盖 _PhysicsProcess(), 给 _PhysicsProcess() 加上了 sealed, 子类需要帧循环函数请重写 PhysicsProcess() 函数
  1181. /// </summary>
  1182. public sealed override void _PhysicsProcess(double delta)
  1183. {
  1184. #if TOOLS
  1185. if (Engine.IsEditorHint())
  1186. {
  1187. return;
  1188. }
  1189. #endif
  1190. var newDelta = (float)delta;
  1191. if (EnableCustomBehavior)
  1192. {
  1193. PhysicsProcess(newDelta);
  1194. }
  1195. //更新组件
  1196. if (_components.Count > 0)
  1197. {
  1198. _updatingComp = true;
  1199. if (EnableCustomBehavior) //启用所有组件
  1200. {
  1201. for (int i = 0; i < _components.Count; i++)
  1202. {
  1203. if (IsDestroyed) return;
  1204. var temp = _components[i].Value;
  1205. if (temp != null && temp.Enable)
  1206. {
  1207. temp.PhysicsProcess(newDelta);
  1208. }
  1209. }
  1210. }
  1211. else //只更新 MoveController 组件
  1212. {
  1213. if (MoveController.Enable)
  1214. {
  1215. MoveController.PhysicsProcess(newDelta);
  1216. }
  1217. }
  1218. _updatingComp = false;
  1219.  
  1220. if (_changeComponents.Count > 0)
  1221. {
  1222. RefreshComponent();
  1223. }
  1224. }
  1225. }
  1226.  
  1227. //更新新增/移除的组件
  1228. private void RefreshComponent()
  1229. {
  1230. for (var i = 0; i < _changeComponents.Count; i++)
  1231. {
  1232. var item = _changeComponents[i];
  1233. if (item.Value) //添加组件
  1234. {
  1235. _components.Add(new KeyValuePair<Type, Component>(item.Key.GetType(), item.Key));
  1236. }
  1237. else //移除组件
  1238. {
  1239. for (var j = 0; j < _components.Count; j++)
  1240. {
  1241. if (_components[i].Value == item.Key)
  1242. {
  1243. _components.RemoveAt(i);
  1244. break;
  1245. }
  1246. }
  1247. }
  1248. }
  1249. }
  1250.  
  1251. /// <summary>
  1252. /// 绘制函数, 子类不允许重写, 需要绘制函数请重写 DebugDraw()
  1253. /// </summary>
  1254. public sealed override void _Draw()
  1255. {
  1256. #if TOOLS
  1257. if (Engine.IsEditorHint())
  1258. {
  1259. return;
  1260. }
  1261. #endif
  1262. if (IsDebug)
  1263. {
  1264. DebugDraw();
  1265. if (_components.Count > 0)
  1266. {
  1267. var arr = _components.ToArray();
  1268. for (int i = 0; i < arr.Length; i++)
  1269. {
  1270. if (IsDestroyed) return;
  1271. var temp = arr[i].Value;
  1272. if (temp != null && temp.Master == this && temp.Enable)
  1273. {
  1274. temp.DebugDraw();
  1275. }
  1276. }
  1277. }
  1278. }
  1279. }
  1280.  
  1281. /// <summary>
  1282. /// 重新计算物体阴影的位置和旋转信息, 无论是否显示阴影
  1283. /// </summary>
  1284. public void CalcShadowTransform()
  1285. {
  1286. //缩放
  1287. ShadowSprite.Scale = AnimatedSprite.Scale;
  1288. //阴影角度
  1289. ShadowSprite.Rotation = 0;
  1290. //阴影位置计算
  1291. var pos = AnimatedSprite.GlobalPosition;
  1292. ShadowSprite.GlobalPosition = new Vector2(pos.X + ShadowOffset.X, pos.Y + ShadowOffset.Y + Altitude);
  1293. }
  1294.  
  1295. //计算位置
  1296. private void CalcThrowAnimatedPosition()
  1297. {
  1298. if (Scale.Y < 0)
  1299. {
  1300. var pos = new Vector2(_fallData.OriginSpritePosition.X, -_fallData.OriginSpritePosition.Y);
  1301. AnimatedSprite.GlobalPosition = GlobalPosition + new Vector2(0, -Altitude) - pos.Rotated(Rotation + Mathf.Pi);
  1302. }
  1303. else
  1304. {
  1305. AnimatedSprite.GlobalPosition = GlobalPosition + new Vector2(0, -Altitude) + _fallData.OriginSpritePosition.Rotated(Rotation);
  1306. }
  1307. }
  1308.  
  1309.  
  1310. /// <summary>
  1311. /// 销毁物体
  1312. /// </summary>
  1313. public void Destroy()
  1314. {
  1315. if (IsDestroyed)
  1316. {
  1317. return;
  1318. }
  1319.  
  1320. IsDestroyed = true;
  1321. if (AffiliationArea != null)
  1322. {
  1323. AffiliationArea.RemoveItem(this);
  1324. }
  1325. QueueFree();
  1326. OnDestroy();
  1327.  
  1328. if (_freezeSprite != null)
  1329. {
  1330. _freezeSprite.Destroy();
  1331. }
  1332. var arr = _components.ToArray();
  1333. for (var i = 0; i < arr.Length; i++)
  1334. {
  1335. arr[i].Value?.Destroy();
  1336. }
  1337.  
  1338. _components.Clear();
  1339. }
  1340.  
  1341. /// <summary>
  1342. /// 延时销毁
  1343. /// </summary>
  1344. public void DelayDestroy()
  1345. {
  1346. CallDeferred(nameof(Destroy));
  1347. }
  1348.  
  1349. /// <summary>
  1350. /// 继承指定物体的运动速率
  1351. /// </summary>
  1352. /// <param name="other">目标对象</param>
  1353. /// <param name="scale">继承的速率缩放</param>
  1354. public void InheritVelocity(ActivityObject other, float scale = 0.5f)
  1355. {
  1356. MoveController.AddVelocity(other.Velocity * scale);
  1357. }
  1358.  
  1359. /// <summary>
  1360. /// 触发投抛动作
  1361. /// </summary>
  1362. private void Throw()
  1363. {
  1364. var parent = GetParent();
  1365. //投抛时必须要加入 YSortLayer 节点下
  1366. if (parent == null)
  1367. {
  1368. this.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  1369. }
  1370. else if (parent == GameApplication.Instance.World.NormalLayer)
  1371. {
  1372. parent.RemoveChild(this);
  1373. this.AddToActivityRoot(RoomLayerEnum.YSortLayer);
  1374. }
  1375.  
  1376. CalcThrowAnimatedPosition();
  1377. //显示阴影
  1378. ShowShadowSprite();
  1379.  
  1380. if (EnableVerticalMotion)
  1381. {
  1382. OnThrowStart();
  1383. }
  1384. }
  1385.  
  1386. /// <summary>
  1387. /// 设置下坠状态下的碰撞器
  1388. /// </summary>
  1389. private void SetFallCollision()
  1390. {
  1391. if (_fallData != null && _fallData.UseOrigin)
  1392. {
  1393. _fallData.OriginShape = Collision.Shape;
  1394. _fallData.OriginPosition = Collision.Position;
  1395. _fallData.OriginRotation = Collision.Rotation;
  1396. _fallData.OriginScale = Collision.Scale;
  1397. _fallData.OriginZIndex = ZIndex;
  1398. _fallData.OriginSpritePosition = AnimatedSprite.Position;
  1399. _fallData.OriginCollisionEnable = Collision.Disabled;
  1400. _fallData.OriginCollisionPosition = Collision.Position;
  1401. _fallData.OriginCollisionRotation = Collision.Rotation;
  1402. _fallData.OriginCollisionScale = Collision.Scale;
  1403. _fallData.OriginCollisionMask = CollisionMask;
  1404. _fallData.OriginCollisionLayer = CollisionLayer;
  1405.  
  1406. if (_throwRectangleShape == null)
  1407. {
  1408. _throwRectangleShape = new RectangleShape2D();
  1409. }
  1410. Collision.Shape = _throwRectangleShape;
  1411. Collision.Position = Vector2.Zero;
  1412. Collision.Rotation = 0;
  1413. Collision.Scale = Vector2.One;
  1414. ZIndex = 0;
  1415. Collision.Disabled = false;
  1416. Collision.Position = Vector2.Zero;
  1417. Collision.Rotation = 0;
  1418. Collision.Scale = Vector2.One;
  1419. CollisionMask = 1;
  1420. CollisionLayer = _fallData.OriginCollisionLayer | PhysicsLayer.Throwing;
  1421. _fallData.UseOrigin = false;
  1422. }
  1423. }
  1424.  
  1425. /// <summary>
  1426. /// 重置碰撞器
  1427. /// </summary>
  1428. private void RestoreCollision()
  1429. {
  1430. if (_fallData != null && !_fallData.UseOrigin)
  1431. {
  1432. Collision.Shape = _fallData.OriginShape;
  1433. Collision.Position = _fallData.OriginPosition;
  1434. Collision.Rotation = _fallData.OriginRotation;
  1435. Collision.Scale = _fallData.OriginScale;
  1436. ZIndex = _fallData.OriginZIndex;
  1437. AnimatedSprite.Position = _fallData.OriginSpritePosition;
  1438. Collision.Disabled = _fallData.OriginCollisionEnable;
  1439. Collision.Position = _fallData.OriginCollisionPosition;
  1440. Collision.Rotation = _fallData.OriginCollisionRotation;
  1441. Collision.Scale = _fallData.OriginCollisionScale;
  1442. CollisionMask = _fallData.OriginCollisionMask;
  1443. CollisionLayer = _fallData.OriginCollisionLayer;
  1444.  
  1445. _fallData.UseOrigin = true;
  1446. }
  1447. }
  1448.  
  1449. /// <summary>
  1450. /// 投抛结束
  1451. /// </summary>
  1452. private void ThrowOver()
  1453. {
  1454. var parent = GetParent();
  1455. var roomLayer = GameApplication.Instance.World.GetRoomLayer(_currLayer);
  1456. if (parent != roomLayer)
  1457. {
  1458. parent.RemoveChild(this);
  1459. roomLayer.AddChild(this);
  1460. }
  1461. RestoreCollision();
  1462.  
  1463. OnThrowOver();
  1464. }
  1465.  
  1466. //初始化投抛状态数据
  1467. private void InitThrowData()
  1468. {
  1469. SetFallCollision();
  1470.  
  1471. _isFallOver = false;
  1472. _firstFall = true;
  1473. _hasResilienceVerticalSpeed = false;
  1474. _resilienceVerticalSpeed = 0;
  1475. if (ThrowCollisionSize.X < 0 && ThrowCollisionSize.Y < 0)
  1476. {
  1477. _throwRectangleShape.Size = GetDefaultTexture().GetSize();
  1478. }
  1479. else
  1480. {
  1481. _throwRectangleShape.Size = ThrowCollisionSize;
  1482. }
  1483.  
  1484. Throw();
  1485. }
  1486.  
  1487. /// <summary>
  1488. /// 设置标记, 用于在物体上记录自定义数据
  1489. /// </summary>
  1490. /// <param name="name">标记名称</param>
  1491. /// <param name="v">存入值</param>
  1492. public void SetSign(string name, object v)
  1493. {
  1494. if (_signMap == null)
  1495. {
  1496. _signMap = new Dictionary<string, object>();
  1497. }
  1498.  
  1499. _signMap[name] = v;
  1500. }
  1501.  
  1502. /// <summary>
  1503. /// 返回是否存在指定名称的标记数据
  1504. /// </summary>
  1505. public bool HasSign(string name)
  1506. {
  1507. return _signMap == null ? false : _signMap.ContainsKey(name);
  1508. }
  1509.  
  1510. /// <summary>
  1511. /// 根据名称获取标记值
  1512. /// </summary>
  1513. public object GetSign(string name)
  1514. {
  1515. if (_signMap == null)
  1516. {
  1517. return null;
  1518. }
  1519.  
  1520. _signMap.TryGetValue(name, out var value);
  1521. return value;
  1522. }
  1523.  
  1524. /// <summary>
  1525. /// 根据名称获取标记值
  1526. /// </summary>
  1527. public T GetSign<T>(string name)
  1528. {
  1529. if (_signMap == null)
  1530. {
  1531. return default;
  1532. }
  1533.  
  1534. _signMap.TryGetValue(name, out var value);
  1535. if (value is T v)
  1536. {
  1537. return v;
  1538. }
  1539. return default;
  1540. }
  1541.  
  1542. /// <summary>
  1543. /// 根据名称删除标记
  1544. /// </summary>
  1545. public void RemoveSign(string name)
  1546. {
  1547. if (_signMap != null)
  1548. {
  1549. _signMap.Remove(name);
  1550. }
  1551. }
  1552.  
  1553. /// <summary>
  1554. /// 播放受伤动画, 该动画不与 Animation 节点的动画冲突
  1555. /// </summary>
  1556. public void PlayHitAnimation()
  1557. {
  1558. _playHit = true;
  1559. _playHitSchedule = 0;
  1560. }
  1561.  
  1562. /// <summary>
  1563. /// 获取当前摩擦力
  1564. /// </summary>
  1565. public float GetCurrentFriction()
  1566. {
  1567. return ActivityMaterial.Friction;
  1568. }
  1569. /// <summary>
  1570. /// 获取当前旋转摩擦力
  1571. /// </summary>
  1572. public float GetCurrentRotationFriction()
  1573. {
  1574. return ActivityMaterial.RotationFriction;
  1575. }
  1576. public long StartCoroutine(IEnumerator able)
  1577. {
  1578. return ProxyCoroutineHandler.ProxyStartCoroutine(ref _coroutineList, able);
  1579. }
  1580. public void StopCoroutine(long coroutineId)
  1581. {
  1582. ProxyCoroutineHandler.ProxyStopCoroutine(ref _coroutineList, coroutineId);
  1583. }
  1584.  
  1585. public bool IsCoroutineOver(long coroutineId)
  1586. {
  1587. return ProxyCoroutineHandler.ProxyIsCoroutineOver(ref _coroutineList, coroutineId);
  1588. }
  1589.  
  1590. public void StopAllCoroutine()
  1591. {
  1592. ProxyCoroutineHandler.ProxyStopAllCoroutine(ref _coroutineList);
  1593. }
  1594. /// <summary>
  1595. /// 播放 AnimatedSprite 上的动画, 如果没有这个动画, 则什么也不会发生
  1596. /// </summary>
  1597. /// <param name="name">动画名称</param>
  1598. public void PlaySpriteAnimation(string name)
  1599. {
  1600. var spriteFrames = AnimatedSprite.SpriteFrames;
  1601. if (spriteFrames != null && spriteFrames.HasAnimation(name))
  1602. {
  1603. AnimatedSprite.Play(name);
  1604. }
  1605. }
  1606.  
  1607. /// <summary>
  1608. /// 将当前 ActivityObject 变成静态图像绘制到地面上, 用于优化渲染大量物体<br/>
  1609. /// 调用该函数后会排队进入渲染队列, 并且禁用所有行为, 当渲染完成后会销毁当前对象, 也就是调用 Destroy() 函数<br/>
  1610. /// </summary>
  1611. public void BecomesStaticImage()
  1612. {
  1613. if (_processingBecomesStaticImage)
  1614. {
  1615. return;
  1616. }
  1617. if (AffiliationArea == null)
  1618. {
  1619. Debug.LogError($"调用函数: BecomesStaticImage() 失败, 物体{Name}没有归属区域, 无法确定绘制到哪个ImageCanvas上, 直接执行销毁");
  1620. Destroy();
  1621. return;
  1622. }
  1623.  
  1624. _processingBecomesStaticImage = true;
  1625. EnableBehavior = false;
  1626. var roomInfo = AffiliationArea.RoomInfo;
  1627. var position = roomInfo.ToImageCanvasPosition(GlobalPosition);
  1628. roomInfo.StaticImageCanvas.DrawActivityObjectInCanvas(this, position.X, position.Y, () =>
  1629. {
  1630. Destroy();
  1631. });
  1632. }
  1633.  
  1634. /// <summary>
  1635. /// 是否正在处理成为静态图片
  1636. /// </summary>
  1637. public bool IsProcessingBecomesStaticImage()
  1638. {
  1639. return _processingBecomesStaticImage;
  1640. }
  1641. /// <summary>
  1642. /// 冻结物体,多余的节点就会被移出场景树,逻辑也会被暂停,用于优化性能
  1643. /// </summary>
  1644. public void Freeze()
  1645. {
  1646. if (_freezeSprite == null)
  1647. {
  1648. _freezeSprite = new FreezeSprite(this);
  1649. }
  1650. _freezeSprite.Freeze();
  1651. }
  1652.  
  1653. /// <summary>
  1654. /// 解冻物体, 恢复正常逻辑
  1655. /// </summary>
  1656. public void Unfreeze()
  1657. {
  1658. if (_freezeSprite == null)
  1659. {
  1660. return;
  1661. }
  1662. _freezeSprite.Unfreeze();
  1663. }
  1664. }