// (c) Copyright HutongGames, LLC 2010-2013. All rights reserved. #if UNITY_EDITOR using System; using System.Linq; using System.Collections.Generic; using System.Reflection; #endif using UnityEngine; namespace HutongGames.PlayMaker.Actions { [ActionCategory(ActionCategory.ScriptControl)] [Tooltip("Start a Coroutine in a Behaviour on a Game Object. See Unity StartCoroutine docs.")] public class StartCoroutine : FsmStateAction { [RequiredField] [Tooltip("The game object that owns the Behaviour.")] public FsmOwnerDefault gameObject; [RequiredField] [UIHint(UIHint.Behaviour)] [Tooltip("The Behaviour that contains the method to start as a coroutine.")] public FsmString behaviour; [RequiredField] [UIHint(UIHint.Coroutine)] [Tooltip("The name of the coroutine method.")] public FunctionCall functionCall; [Tooltip("Stop the coroutine when the state is exited.")] public bool stopOnExit; public override void Reset() { gameObject = null; behaviour = null; functionCall = null; stopOnExit = false; } MonoBehaviour component; #if UNITY_EDITOR private Type cachedType; private List methodNames; #endif public override void OnEnter() { DoStartCoroutine(); Finish(); } void DoStartCoroutine() { var go = Fsm.GetOwnerDefaultTarget(gameObject); if (go == null) { return; } component = go.GetComponent(ReflectionUtils.GetGlobalType(behaviour.Value)) as MonoBehaviour; if (component == null) { LogWarning("StartCoroutine: " + go.name + " missing behaviour: " + behaviour.Value); return; } switch (functionCall.ParameterType) { case "None": component.StartCoroutine(functionCall.FunctionName); return; case "int": component.StartCoroutine(functionCall.FunctionName, functionCall.IntParameter.Value); return; case "float": component.StartCoroutine(functionCall.FunctionName, functionCall.FloatParameter.Value); return; case "string": component.StartCoroutine(functionCall.FunctionName, functionCall.StringParameter.Value); return; case "bool": component.StartCoroutine(functionCall.FunctionName, functionCall.BoolParameter.Value); return; case "Vector2": component.StartCoroutine(functionCall.FunctionName, functionCall.Vector2Parameter.Value); return; case "Vector3": component.StartCoroutine(functionCall.FunctionName, functionCall.Vector3Parameter.Value); return; case "Rect": component.StartCoroutine(functionCall.FunctionName, functionCall.RectParamater.Value); return; case "GameObject": component.StartCoroutine(functionCall.FunctionName, functionCall.GameObjectParameter.Value); return; case "Material": component.StartCoroutine(functionCall.FunctionName, functionCall.MaterialParameter.Value); break; case "Texture": component.StartCoroutine(functionCall.FunctionName, functionCall.TextureParameter.Value); break; case "Quaternion": component.StartCoroutine(functionCall.FunctionName, functionCall.QuaternionParameter.Value); break; case "Object": component.StartCoroutine(functionCall.FunctionName, functionCall.ObjectParameter.Value); return; } } public override void OnExit() { if (component == null) { return; } if (stopOnExit) { component.StopCoroutine(functionCall.FunctionName); } } #if UNITY_EDITOR public override string ErrorCheck() { var go = Fsm.GetOwnerDefaultTarget(gameObject); if (go == null || string.IsNullOrEmpty(behaviour.Value)) { return string.Empty; } var type = ReflectionUtils.GetGlobalType(behaviour.Value); if (type == null) { return "Missing Behaviour: " + behaviour.Value; } if (cachedType != type) { cachedType = type; methodNames = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Select(m => m.Name).ToList(); } if (!string.IsNullOrEmpty(functionCall.FunctionName)) { if (!methodNames.Contains(functionCall.FunctionName)) { return "Missing Method: " + functionCall.FunctionName; } } return string.Empty; } #endif } }