Skip to main content
Glama
RobotAnimator.cs7.37 kB
using UnityEngine; using System.Collections.Generic; /// <summary> /// Animation controller for virtual robots in Unity. /// Handles wheel rotation, movement animations, poses, and custom animations. /// Used by robotics-mcp robot_animation tool via execute_unity_method. /// </summary> public class RobotAnimator : MonoBehaviour { private static Dictionary<string, RobotAnimator> instances = new Dictionary<string, RobotAnimator>(); [Header("Animation Settings")] public float wheelRotationSpeed = 100f; public float animationSpeed = 1f; private Animator animator; private Dictionary<string, GameObject> wheels = new Dictionary<string, GameObject>(); private string currentAnimation = ""; private bool isAnimating = false; void Awake() { animator = GetComponent<Animator>(); if (animator == null) { animator = gameObject.AddComponent<Animator>(); } // Find wheels by name (Scout has 4 mecanum wheels) FindWheels(); } void FindWheels() { wheels.Clear(); Transform[] allChildren = GetComponentsInChildren<Transform>(); foreach (Transform child in allChildren) { string name = child.name.ToLower(); if (name.Contains("wheel")) { if (name.Contains("front") && name.Contains("left")) wheels["front_left"] = child.gameObject; else if (name.Contains("front") && name.Contains("right")) wheels["front_right"] = child.gameObject; else if (name.Contains("back") && name.Contains("left")) wheels["back_left"] = child.gameObject; else if (name.Contains("back") && name.Contains("right")) wheels["back_right"] = child.gameObject; } } } /// <summary> /// Animate wheels with individual speeds (for mecanum wheels). /// </summary> public static bool AnimateWheels(string robotId, Dictionary<string, float> wheelSpeeds) { RobotAnimator instance = GetInstance(robotId); if (instance == null) return false; instance.AnimateWheelsInstance(wheelSpeeds); return true; } private void AnimateWheelsInstance(Dictionary<string, float> wheelSpeeds) { foreach (var kvp in wheelSpeeds) { if (wheels.ContainsKey(kvp.Key)) { GameObject wheel = wheels[kvp.Key]; float rotation = kvp.Value * wheelRotationSpeed * Time.deltaTime; wheel.transform.Rotate(0, 0, rotation, Space.Self); } } } /// <summary> /// Animate movement (walk, turn, etc.). /// </summary> public static bool AnimateMovement(string robotId, string animationName, float speed, bool loop) { RobotAnimator instance = GetInstance(robotId); if (instance == null) return false; instance.AnimateMovementInstance(animationName, speed, loop); return true; } private void AnimateMovementInstance(string animationName, float speed, bool loop) { if (animator != null && animator.runtimeAnimatorController != null) { animator.speed = speed; animator.SetBool("Loop", loop); animator.Play(animationName); currentAnimation = animationName; isAnimating = true; } else { Debug.LogWarning($"No Animator Controller found for {gameObject.name}. Movement animation '{animationName}' not played."); } } /// <summary> /// Set robot pose (sit, stand, crouch, etc.). /// </summary> public static bool SetPose(string robotId, string pose) { RobotAnimator instance = GetInstance(robotId); if (instance == null) return false; instance.SetPoseInstance(pose); return true; } private void SetPoseInstance(string pose) { if (animator != null && animator.runtimeAnimatorController != null) { animator.SetTrigger(pose); Debug.Log($"{gameObject.name} pose set to: {pose}"); } else { Debug.LogWarning($"No Animator Controller found for {gameObject.name}. Pose '{pose}' not set."); } } /// <summary> /// Play custom animation. /// </summary> public static bool PlayAnimation(string robotId, string animationName, float speed, bool loop) { RobotAnimator instance = GetInstance(robotId); if (instance == null) return false; instance.PlayAnimationInstance(animationName, speed, loop); return true; } private void PlayAnimationInstance(string animationName, float speed, bool loop) { if (animator != null && animator.runtimeAnimatorController != null) { animator.speed = speed; animator.SetBool("Loop", loop); animator.Play(animationName); currentAnimation = animationName; isAnimating = true; } else { Debug.LogWarning($"No Animator Controller found for {gameObject.name}. Animation '{animationName}' not played."); } } /// <summary> /// Stop current animation. /// </summary> public static bool StopAnimation(string robotId) { RobotAnimator instance = GetInstance(robotId); if (instance == null) return false; instance.StopAnimationInstance(); return true; } private void StopAnimationInstance() { if (animator != null) { animator.speed = 0f; isAnimating = false; currentAnimation = ""; } } /// <summary> /// Get current animation state. /// </summary> public static Dictionary<string, object> GetAnimationState(string robotId) { RobotAnimator instance = GetInstance(robotId); if (instance == null) return null; return instance.GetAnimationStateInstance(); } private Dictionary<string, object> GetAnimationStateInstance() { return new Dictionary<string, object> { {"currentAnimation", currentAnimation}, {"isAnimating", isAnimating}, {"animationSpeed", animator != null ? animator.speed : 0f}, {"hasAnimator", animator != null && animator.runtimeAnimatorController != null} }; } private static RobotAnimator GetInstance(string robotId) { if (instances.ContainsKey(robotId)) { return instances[robotId]; } GameObject robot = GameObject.Find(robotId); if (robot == null) { Debug.LogError($"Robot with ID '{robotId}' not found in scene."); return null; } RobotAnimator animator = robot.GetComponent<RobotAnimator>(); if (animator == null) { animator = robot.AddComponent<RobotAnimator>(); } instances[robotId] = animator; return animator; } void OnDestroy() { instances.Remove(gameObject.name); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/sandraschi/robotics-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server