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