Advertisement
Guest User

Untitled

a guest
Aug 23rd, 2019
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 19.26 KB | None | 0 0
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4.  
  5. namespace BTAI
  6. {
  7. public enum BTState
  8. {
  9. Failure,
  10. Success,
  11. Continue,
  12. Abort
  13. }
  14.  
  15. public static class BT
  16. {
  17. public static Root Root() { return new Root(); }
  18. public static Sequence Sequence() { return new Sequence(); }
  19. public static Selector Selector(bool shuffle = false) { return new Selector(shuffle); }
  20. public static Action RunCoroutine(System.Func<IEnumerator<BTState>> coroutine) { return new Action(coroutine); }
  21. public static Action Call(System.Action fn) { return new Action(fn); }
  22. public static ConditionalBranch If(System.Func<bool> fn) { return new ConditionalBranch(fn); }
  23. public static While While(System.Func<bool> fn) { return new While(fn); }
  24. public static Condition Condition(System.Func<bool> fn) { return new Condition(fn); }
  25. public static Repeat Repeat(int count) { return new Repeat(count); }
  26. public static Wait Wait(float seconds) { return new Wait(seconds); }
  27. public static Trigger Trigger(Animator animator, string name, bool set = true) { return new Trigger(animator, name, set); }
  28. public static WaitForAnimatorState WaitForAnimatorState(Animator animator, string name, int layer = 0) { return new WaitForAnimatorState(animator, name, layer); }
  29. public static SetBool SetBool(Animator animator, string name, bool value) { return new SetBool(animator, name, value); }
  30. public static SetActive SetActive(GameObject gameObject, bool active) { return new SetActive(gameObject, active); }
  31. public static WaitForAnimatorSignal WaitForAnimatorSignal(Animator animator, string name, string state, int layer = 0) { return new WaitForAnimatorSignal(animator, name, state, layer); }
  32. public static Terminate Terminate() { return new Terminate(); }
  33. public static Log Log(string msg) { return new Log(msg); }
  34. public static RandomSequence RandomSequence(int[] weights = null) { return new BTAI.RandomSequence(weights); }
  35.  
  36. }
  37.  
  38. public abstract class BTNode
  39. {
  40. public abstract BTState Tick();
  41. }
  42.  
  43. public abstract class Branch : BTNode
  44. {
  45. protected int activeChild;
  46. protected List<BTNode> children = new List<BTNode>();
  47. public virtual Branch OpenBranch(params BTNode[] children)
  48. {
  49. for (var i = 0; i < children.Length; i++)
  50. this.children.Add(children[i]);
  51. return this;
  52. }
  53.  
  54. public List<BTNode> Children()
  55. {
  56. return children;
  57. }
  58.  
  59. public int ActiveChild()
  60. {
  61. return activeChild;
  62. }
  63.  
  64. public virtual void ResetChildren()
  65. {
  66. activeChild = 0;
  67. for (var i = 0; i < children.Count; i++)
  68. {
  69. Branch b = children[i] as Branch;
  70. if (b != null)
  71. {
  72. b.ResetChildren();
  73. }
  74. }
  75. }
  76. }
  77.  
  78. public abstract class Decorator : BTNode
  79. {
  80. protected BTNode child;
  81. public Decorator Do(BTNode child)
  82. {
  83. this.child = child;
  84. return this;
  85. }
  86. }
  87.  
  88. public class Sequence : Branch
  89. {
  90. public override BTState Tick()
  91. {
  92. var childState = children[activeChild].Tick();
  93. switch (childState)
  94. {
  95. case BTState.Success:
  96. activeChild++;
  97. if (activeChild == children.Count)
  98. {
  99. activeChild = 0;
  100. return BTState.Success;
  101. }
  102. else
  103. return BTState.Continue;
  104. case BTState.Failure:
  105. activeChild = 0;
  106. return BTState.Failure;
  107. case BTState.Continue:
  108. return BTState.Continue;
  109. case BTState.Abort:
  110. activeChild = 0;
  111. return BTState.Abort;
  112. }
  113. throw new System.Exception("This should never happen, but clearly it has.");
  114. }
  115. }
  116.  
  117. /// <summary>
  118. /// Execute each child until a child succeeds, then return success.
  119. /// If no child succeeds, return a failure.
  120. /// </summary>
  121. public class Selector : Branch
  122. {
  123. public Selector(bool shuffle)
  124. {
  125. if (shuffle)
  126. {
  127. var n = children.Count;
  128. while (n > 1)
  129. {
  130. n--;
  131. var k = Mathf.FloorToInt(Random.value * (n + 1));
  132. var value = children[k];
  133. children[k] = children[n];
  134. children[n] = value;
  135. }
  136. }
  137. }
  138.  
  139. public override BTState Tick()
  140. {
  141. var childState = children[activeChild].Tick();
  142. switch (childState)
  143. {
  144. case BTState.Success:
  145. activeChild = 0;
  146. return BTState.Success;
  147. case BTState.Failure:
  148. activeChild++;
  149. if (activeChild == children.Count)
  150. {
  151. activeChild = 0;
  152. return BTState.Failure;
  153. }
  154. else
  155. return BTState.Continue;
  156. case BTState.Continue:
  157. return BTState.Continue;
  158. case BTState.Abort:
  159. activeChild = 0;
  160. return BTState.Abort;
  161. }
  162. throw new System.Exception("This should never happen, but clearly it has.");
  163. }
  164. }
  165.  
  166. /// <summary>
  167. /// Call a method, or run a coroutine.
  168. /// </summary>
  169. public class Action : BTNode
  170. {
  171. System.Action fn;
  172. System.Func<IEnumerator<BTState>> coroutineFactory;
  173. IEnumerator<BTState> coroutine;
  174. public Action(System.Action fn)
  175. {
  176. this.fn = fn;
  177. }
  178. public Action(System.Func<IEnumerator<BTState>> coroutineFactory)
  179. {
  180. this.coroutineFactory = coroutineFactory;
  181. }
  182. public override BTState Tick()
  183. {
  184. if (fn != null)
  185. {
  186. fn();
  187. return BTState.Success;
  188. }
  189. else
  190. {
  191. if (coroutine == null)
  192. coroutine = coroutineFactory();
  193. if (!coroutine.MoveNext())
  194. {
  195. coroutine = null;
  196. return BTState.Success;
  197. }
  198. var result = coroutine.Current;
  199. if (result == BTState.Continue)
  200. return BTState.Continue;
  201. else
  202. {
  203. coroutine = null;
  204. return result;
  205. }
  206. }
  207. }
  208.  
  209. public override string ToString()
  210. {
  211. return "Action : " + fn.Method.ToString();
  212. }
  213. }
  214.  
  215. /// <summary>
  216. /// Call a method, returns success if method returns true, else returns failure.
  217. /// </summary>
  218. public class Condition : BTNode
  219. {
  220. public System.Func<bool> fn;
  221.  
  222. public Condition(System.Func<bool> fn)
  223. {
  224. this.fn = fn;
  225. }
  226. public override BTState Tick()
  227. {
  228. return fn() ? BTState.Success : BTState.Failure;
  229. }
  230.  
  231. public override string ToString()
  232. {
  233. return "Condition : " + fn.Method.ToString();
  234. }
  235. }
  236.  
  237. public class ConditionalBranch : Block
  238. {
  239. public System.Func<bool> fn;
  240. bool tested = false;
  241. public ConditionalBranch(System.Func<bool> fn)
  242. {
  243. this.fn = fn;
  244. }
  245. public override BTState Tick()
  246. {
  247. if (!tested)
  248. {
  249. tested = fn();
  250. }
  251. if (tested)
  252. {
  253. var result = base.Tick();
  254. if (result == BTState.Continue)
  255. return BTState.Continue;
  256. else
  257. {
  258. tested = false;
  259. return result;
  260. }
  261. }
  262. else
  263. {
  264. return BTState.Failure;
  265. }
  266. }
  267.  
  268. public override string ToString()
  269. {
  270. return "ConditionalBranch : " + fn.Method.ToString();
  271. }
  272. }
  273.  
  274. /// <summary>
  275. /// Run all children, while method returns true.
  276. /// </summary>
  277. public class While : Block
  278. {
  279. public System.Func<bool> fn;
  280.  
  281. public While(System.Func<bool> fn)
  282. {
  283. this.fn = fn;
  284. }
  285.  
  286. public override BTState Tick()
  287. {
  288. if (fn())
  289. base.Tick();
  290. else
  291. {
  292. //if we exit the loop
  293. ResetChildren();
  294. return BTState.Failure;
  295. }
  296.  
  297. return BTState.Continue;
  298. }
  299.  
  300. public override string ToString()
  301. {
  302. return "While : " + fn.Method.ToString();
  303. }
  304. }
  305.  
  306. public abstract class Block : Branch
  307. {
  308. public override BTState Tick()
  309. {
  310. switch (children[activeChild].Tick())
  311. {
  312. case BTState.Continue:
  313. return BTState.Continue;
  314. default:
  315. activeChild++;
  316. if (activeChild == children.Count)
  317. {
  318. activeChild = 0;
  319. return BTState.Success;
  320. }
  321. return BTState.Continue;
  322. }
  323. }
  324. }
  325.  
  326. public class Root : Block
  327. {
  328. public bool isTerminated = false;
  329.  
  330. public override BTState Tick()
  331. {
  332. if (isTerminated) return BTState.Abort;
  333. while (true)
  334. {
  335. switch (children[activeChild].Tick())
  336. {
  337. case BTState.Continue:
  338. return BTState.Continue;
  339. case BTState.Abort:
  340. isTerminated = true;
  341. return BTState.Abort;
  342. default:
  343. activeChild++;
  344. if (activeChild == children.Count)
  345. {
  346. activeChild = 0;
  347. return BTState.Success;
  348. }
  349. continue;
  350. }
  351. }
  352. }
  353. }
  354.  
  355. /// <summary>
  356. /// Run a block of children a number of times.
  357. /// </summary>
  358. public class Repeat : Block
  359. {
  360. public int count = 1;
  361. int currentCount = 0;
  362. public Repeat(int count)
  363. {
  364. this.count = count;
  365. }
  366. public override BTState Tick()
  367. {
  368. if (count > 0 && currentCount < count)
  369. {
  370. var result = base.Tick();
  371. switch (result)
  372. {
  373. case BTState.Continue:
  374. return BTState.Continue;
  375. default:
  376. currentCount++;
  377. if (currentCount == count)
  378. {
  379. currentCount = 0;
  380. return BTState.Success;
  381. }
  382. return BTState.Continue;
  383. }
  384. }
  385. return BTState.Success;
  386. }
  387.  
  388. public override string ToString()
  389. {
  390. return "Repeat Until : " + currentCount + " / " + count;
  391. }
  392. }
  393.  
  394. public class RandomSequence : Block
  395. {
  396. int[] m_Weight = null;
  397. int[] m_AddedWeight = null;
  398.  
  399. /// <summary>
  400. /// Will select one random child everytime it get triggered again
  401. /// </summary>
  402. /// <param name="weight">Leave null so that all child node have the same weight.
  403. /// If there is less weight than children, all subsequent child will have weight = 1</param>
  404. public RandomSequence(int[] weight = null)
  405. {
  406. activeChild = -1;
  407.  
  408. m_Weight = weight;
  409. }
  410.  
  411. public override Branch OpenBranch(params BTNode[] children)
  412. {
  413. m_AddedWeight = new int[children.Length];
  414.  
  415. for (int i = 0; i < children.Length; ++i)
  416. {
  417. int weight = 0;
  418. int previousWeight = 0;
  419.  
  420. if (m_Weight == null || m_Weight.Length <= i)
  421. {//if we don't have weight for that one, we set the weight to one
  422. weight = 1;
  423. }
  424. else
  425. weight = m_Weight[i];
  426.  
  427. if (i > 0)
  428. previousWeight = m_AddedWeight[i - 1];
  429.  
  430. m_AddedWeight[i] = weight + previousWeight;
  431. }
  432.  
  433. return base.OpenBranch(children);
  434. }
  435.  
  436. public override BTState Tick()
  437. {
  438. if (activeChild == -1)
  439. PickNewChild();
  440.  
  441. var result = children[activeChild].Tick();
  442.  
  443. switch (result)
  444. {
  445. case BTState.Continue:
  446. return BTState.Continue;
  447. default:
  448. PickNewChild();
  449. return result;
  450. }
  451. }
  452.  
  453. void PickNewChild()
  454. {
  455. int choice = Random.Range(0, m_AddedWeight[m_AddedWeight.Length - 1]);
  456.  
  457. for (int i = 0; i < m_AddedWeight.Length; ++i)
  458. {
  459. if (choice - m_AddedWeight[i] <= 0)
  460. {
  461. activeChild = i;
  462. break;
  463. }
  464. }
  465. }
  466.  
  467. public override string ToString()
  468. {
  469. return "Random Sequence : " + activeChild + "/" + children.Count;
  470. }
  471. }
  472.  
  473.  
  474. /// <summary>
  475. /// Pause execution for a number of seconds.
  476. /// </summary>
  477. public class Wait : BTNode
  478. {
  479. public float seconds = 0;
  480. float future = -1;
  481. public Wait(float seconds)
  482. {
  483. this.seconds = seconds;
  484. }
  485.  
  486. public override BTState Tick()
  487. {
  488. if (future < 0)
  489. future = Time.time + seconds;
  490.  
  491. if (Time.time >= future)
  492. {
  493. future = -1;
  494. return BTState.Success;
  495. }
  496. else
  497. return BTState.Continue;
  498. }
  499.  
  500. public override string ToString()
  501. {
  502. return "Wait : " + (future - Time.time) + " / " + seconds;
  503. }
  504. }
  505.  
  506. /// <summary>
  507. /// Activate a trigger on an animator.
  508. /// </summary>
  509. public class Trigger : BTNode
  510. {
  511. Animator animator;
  512. int id;
  513. string triggerName;
  514. bool set = true;
  515.  
  516. //if set == false, it reset the trigger istead of setting it.
  517. public Trigger(Animator animator, string name, bool set = true)
  518. {
  519. this.id = Animator.StringToHash(name);
  520. this.animator = animator;
  521. this.triggerName = name;
  522. this.set = set;
  523. }
  524.  
  525. public override BTState Tick()
  526. {
  527. if (set)
  528. animator.SetTrigger(id);
  529. else
  530. animator.ResetTrigger(id);
  531.  
  532. return BTState.Success;
  533. }
  534.  
  535. public override string ToString()
  536. {
  537. return "Trigger : " + triggerName;
  538. }
  539. }
  540.  
  541. /// <summary>
  542. /// Set a boolean on an animator.
  543. /// </summary>
  544. public class SetBool : BTNode
  545. {
  546. Animator animator;
  547. int id;
  548. bool value;
  549. string triggerName;
  550.  
  551. public SetBool(Animator animator, string name, bool value)
  552. {
  553. this.id = Animator.StringToHash(name);
  554. this.animator = animator;
  555. this.value = value;
  556. this.triggerName = name;
  557. }
  558.  
  559. public override BTState Tick()
  560. {
  561. animator.SetBool(id, value);
  562. return BTState.Success;
  563. }
  564.  
  565. public override string ToString()
  566. {
  567. return "SetBool : " + triggerName + " = " + value.ToString();
  568. }
  569. }
  570.  
  571. /// <summary>
  572. /// Wait for an animator to reach a state.
  573. /// </summary>
  574. public class WaitForAnimatorState : BTNode
  575. {
  576. Animator animator;
  577. int id;
  578. int layer;
  579. string stateName;
  580.  
  581. public WaitForAnimatorState(Animator animator, string name, int layer = 0)
  582. {
  583. this.id = Animator.StringToHash(name);
  584. if (!animator.HasState(layer, this.id))
  585. {
  586. Debug.LogError("The animator does not have state: " + name);
  587. }
  588. this.animator = animator;
  589. this.layer = layer;
  590. this.stateName = name;
  591. }
  592.  
  593. public override BTState Tick()
  594. {
  595. var state = animator.GetCurrentAnimatorStateInfo(layer);
  596. if (state.fullPathHash == this.id || state.shortNameHash == this.id)
  597. return BTState.Success;
  598. return BTState.Continue;
  599. }
  600.  
  601. public override string ToString()
  602. {
  603. return "Wait For State : " + stateName;
  604. }
  605. }
  606.  
  607. /// <summary>
  608. /// Set a gameobject active flag.
  609. /// </summary>
  610. public class SetActive : BTNode
  611. {
  612.  
  613. GameObject gameObject;
  614. bool active;
  615.  
  616. public SetActive(GameObject gameObject, bool active)
  617. {
  618. this.gameObject = gameObject;
  619. this.active = active;
  620. }
  621.  
  622. public override BTState Tick()
  623. {
  624. gameObject.SetActive(this.active);
  625. return BTState.Success;
  626. }
  627.  
  628. public override string ToString()
  629. {
  630. return "Set Active : " + gameObject.name + " = " + active;
  631. }
  632. }
  633.  
  634. /*
  635. /// <summary>
  636. /// Wait for a signal to be received from a SendSignal state machine behaviour on an animator.
  637. /// </summary>
  638. public class WaitForAnimatorSignal : BTNode
  639. {
  640. internal bool isSet = false;
  641. string name;
  642. int id;
  643.  
  644. public WaitForAnimatorSignal(Animator animator, string name, string state, int layer = 0)
  645. {
  646. this.name = name;
  647. this.id = Animator.StringToHash(name);
  648. if (!animator.HasState(layer, this.id))
  649. {
  650. Debug.LogError("The animator does not have state: " + name);
  651. }
  652. else
  653. {
  654. SendSignal.Register(animator, name, this);
  655. }
  656. }
  657.  
  658. public override BTState Tick()
  659. {
  660. if (!isSet)
  661. return BTState.Continue;
  662. else
  663. {
  664. isSet = false;
  665. return BTState.Success;
  666. }
  667.  
  668. }
  669.  
  670. public override string ToString()
  671. {
  672. return "Wait For Animator Signal : " + name;
  673. }
  674. }
  675. */
  676.  
  677. public class Terminate : BTNode
  678. {
  679.  
  680. public override BTState Tick()
  681. {
  682. return BTState.Abort;
  683. }
  684.  
  685. }
  686.  
  687. public class Log : BTNode
  688. {
  689. string msg;
  690.  
  691. public Log(string msg)
  692. {
  693. this.msg = msg;
  694. }
  695.  
  696. public override BTState Tick()
  697. {
  698. Debug.Log(msg);
  699. return BTState.Success;
  700. }
  701. }
  702.  
  703. }
  704.  
  705. #if UNITY_EDITOR
  706. namespace BTAI
  707. {
  708. public interface IBTDebugable
  709. {
  710. Root GetAIRoot();
  711. }
  712. }
  713. #endif
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement