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