欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 会展 > Unity3D仿星露谷物语开发23之拿起道具的动画

Unity3D仿星露谷物语开发23之拿起道具的动画

2025/2/25 5:38:48 来源:https://blog.csdn.net/benben044/article/details/145150097  浏览:    关键词:Unity3D仿星露谷物语开发23之拿起道具的动画

1、目标

当点击库存栏上可以carry的道具时,首先arms替换为carry状态,同时手上拿着被点击的道具。当再次点击同一个道具时,ams替换为idle状态,手上放下之前的道具。

这个最主要的是要学会使用AnimatorOverrideController类。

2、概念

AnimatorOverrideController类:用于控制动画其重写控制器的接口。

动画器重写控制器的用途是重写某个控制器的动画剪辑,从而为给定化身定制动画。在运行时基于相同的AnimatorController交换Animator.runtimeAnimatorController和AnimatorOverrideController不会重置状态机的当前状态。

(1)一般使用方法

定义变量:AnimatorOverrideController animatorOverrideController;

初始化变量:animatorOverrideController = new AnimatorOverrideController(animator.runtimeAnimatorController);

animator.runtimeAnimatorController = animatorOverrideController;

通过上面的赋值,后续对animatorOverrideController的修改将直接作用于animator.runtimeAnimatorController(运行态的动画控制器)。

运行中更新动画:animatorOverrideController["shot"] = weaponAnimationClip[weaponIndex];

(2)每帧更新多个动画剪辑

使用AnimatorOverrideController.ApplyOverrides方法,它能够将动画器剪辑绑定重新分配的数量减少到每次调用只有一个。

定义新老动画的映射:List<KeyValuePair<AnimationClip, AnimationClip>> clipOverrides;

初始化:animatorOverrideController.GetOverrides(clipOverrides);

运行中更新动画:animatorOverrideController.ApplyOverrides(clipOverrides);

其中ApplyOverrides函数:对该动画器重写控制器应用写列表

GetOverrides函数:获取该动画器重写控制器中当前定义的动画剪辑重写的列表。

3、思路

首先,创建SO_AnimationType类描述所有的动画剪辑。

其次,创建CharacterAttribute类定义想要替换的动画信息。

然后,基于AnimatorOverrideController类,根据CharacterAttribute类定义的动画信息,将Player下所有当前状态的动画替换为CharacterAttribute类定义的动画。

最后,如果是carry状态,给Player下的equippedItem对象赋以点击道具的图像。

4、创建可交互的动画的描述类

在Assets -> Scripts -> Animation下创建SO_AnimationType.cs脚本。

[CreateAssetMenu(fileName = "so_AnimationType", menuName = "Scriptable Objects/Animation/Animation Type")]
public class SO_AnimationType : ScriptableObject
{public AnimationClip animationClip;  // a reference to the actual animation clip  动画剪辑public AnimationName animationName;  // an enum of the animation name like "AnimationName.IdleUp"  动画名称public CharacterPartAnimator characterPart; // the gameobject name the Animator is on that controls these animation clips e.g. "arms" 动画位置对象public PartVariantColour partVariantColour; // to enable colour variations on a animation type to be specified e.g. "none", "bronze", "silver", "gold" 动画颜色变化public PartVariantType partVariantType; // the variant type to specify what variant this animation type refers to e.g. "none", "carry", "hoe", "pickaxe", "axe"..etc 动画类型
}

5、创建一个角色属性结构描述想要交换的动画

在Assets -> Scripts -> Animation 下创建CharacterAttribute.cs脚本,目标动画剪辑的属性结构。

[System.Serializable]
public struct CharacterAttribute
{public CharacterPartAnimator characterPart;   // 示例: CharacterPartAnimator.arms 动画位置对象public PartVariantColour partVariantColour;  // 示例: ParVariantColour.none 动画颜色变化public PartVariantType partVariantType;  // 示例: PartVariantType.carry 动画类型public CharacterAttribute(CharacterPartAnimator characterPart, PartVariantColour partVariantColour, PartVariantType partVariantType) {this.characterPart = characterPart;this.partVariantColour = partVariantColour;this.partVariantType = partVariantType;}
}

6、创建Enum对象

在Assets -> Scripts -> Enums -> Enums.cs 中增加如下信息:

public enum AnimationName
{idleDown,idleUp,idleLeft,idleRight,walkUp,walkDown,walkLeft,walkRight,runUp,runDown,runLeft,runRight,useToolUp,useToolDown,useToolLeft,useToolRight,swingToolUp,swingToolDown,swingToolLeft,swingToolRight,liftToolUp,liftToolDown,liftToolLeft,liftToolRight,holdToolUp,holdToolDown,holdToolLeft,holdToolRight,pickUp,pickDown,pickLeft,pickRight,count
}public enum CharacterPartAnimator
{body,arms,hair,tool,hat,count
}public enum PartVariantColour
{none,count
}public enum PartVariantType
{none,carry,hoe,pickaxe,axe,scythe,wateringCan,count
}

7、创建动画重写控制器AnimationOverrides

流程:

1)创建2个动画剪辑的映射,第1个是 动画剪辑 到 动画描述类的映射,第2个是 动画表示名 到 动画描述类的映射。

2)通过配置的动画描述信息,分别填充上一步的两个映射表。

3)输入characterAttributesList,需要的动作的动画描述信息,比如partVariantType为carry的动画描述。

4)根据characterPart(比如arm)扫描当前角色下已有的动画剪辑,找到characterPart这个名称的动画剪辑为currentAnimator

5)找到characterPart对应controller下所有的动画剪辑,得到animationsList列表

我们找到了arms的animatorController,

再点击进入控制器的Run分类,

点击RunRight,其对应的动画剪辑为ArmsNoneNoneRunRight = characterPart + partVariantColour + partVariantType + animationName

6)在animationsList列表中,依次遍历得到动画剪辑animationClip对应的动画描述类so_AnimationType(已有的动画)

7)然后根据characterAttribute(目标动画属性结构)中的信息+ 动画名称(比如RunRight)搜索目标动画剪辑swapSO_AnimationType

8)然后将animationClip 和 swapSO_AnimationType.animationClip的动画剪辑KeyValuePair<AnimationClip, AnimationClip>结构的animsKeyValuePairList中

9)通过aoc.ApplyOverrides让这些动画剪辑替换生效。

代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class AnimationOverrides : MonoBehaviour
{[SerializeField] private GameObject character = null;[SerializeField] private SO_AnimationType[] soAnimationTypeArray = null;private Dictionary<AnimationClip, SO_AnimationType> animationTypeDictionaryByAnimation;private Dictionary<string, SO_AnimationType> animationTypeDictionaryByCompositeAttributeKey;private void Start(){// Initialise animation type dictionary keyed by animation clipanimationTypeDictionaryByAnimation = new Dictionary<AnimationClip, SO_AnimationType>();foreach(SO_AnimationType item in soAnimationTypeArray){animationTypeDictionaryByAnimation.Add(item.animationClip, item);}// Initialise animation type dictionary keyed by stringanimationTypeDictionaryByCompositeAttributeKey = new Dictionary<string, SO_AnimationType>();foreach (SO_AnimationType item in soAnimationTypeArray) {string key = item.characterPart.ToString() + item.partVariantColour.ToString() + item.partVariantType.ToString() + item.animationName.ToString();animationTypeDictionaryByCompositeAttributeKey.Add(key, item);}}public void ApplyCharacterCustomisationParameters(List<CharacterAttribute> characterAttributesList){// Loop through all character attributes and set the animation override controller for eachforeach (CharacterAttribute characterAttribute in characterAttributesList){Animator currentAnimator = null;List<KeyValuePair<AnimationClip, AnimationClip>> animsKeyValuePairList = new List<KeyValuePair<AnimationClip, AnimationClip>>();string animatorSOAssetName = characterAttribute.characterPart.ToString();// Find animators in scene that match scriptable object animator typeAnimator[] animatorArray = character.GetComponentsInChildren<Animator>();foreach (Animator animator in animatorArray){if (animator.name == animatorSOAssetName){currentAnimator = animator;break;}}// Get base current animations for animatorAnimatorOverrideController aoc = new AnimatorOverrideController(currentAnimator.runtimeAnimatorController);List<AnimationClip> animationsList = new List<AnimationClip>(aoc.animationClips);foreach (AnimationClip animationClip in animationsList){// find animation in dictionarySO_AnimationType so_AnimationType;bool foundAnimation = animationTypeDictionaryByAnimation.TryGetValue(animationClip, out so_AnimationType);if (foundAnimation){string key = characterAttribute.characterPart.ToString() + characterAttribute.partVariantColour.ToString() +characterAttribute.partVariantType.ToString() + so_AnimationType.animationName.ToString();  // 目标动画stringSO_AnimationType swapSO_AnimationType;bool foundSwapAnimation = animationTypeDictionaryByCompositeAttributeKey.TryGetValue(key, out swapSO_AnimationType);if (foundSwapAnimation){AnimationClip swapAnimationClip = swapSO_AnimationType.animationClip;animsKeyValuePairList.Add(new KeyValuePair<AnimationClip, AnimationClip>(animationClip, swapAnimationClip));}}}// Apply animation updates to animation override controller and then update animator with the new controlleraoc.ApplyOverrides(animsKeyValuePairList);currentAnimator.runtimeAnimatorController = aoc;}}}

8、修改Player.cs脚本

创建相关的变量:

private AnimationOverrides animationOverrides;  // 动画重写控制器
private List<CharacterAttribute> characterAttributeCustomisationList;  // 目标动作列表[Tooltip("Should be populated in the prefab with the equippped item sprite renderer")]
[SerializeField] private SpriteRenderer equippedItemSpriteRenderer = null; // 武器的图片

在Awake中初始化相关变量:

// Initialise swappable character attributes
armsCharacterAttribute = new CharacterAttribute(CharacterPartAnimator.arms, PartVariantColour.none, PartVariantType.none);// Initialise character attribute list
characterAttributeCustomisationList = new List<CharacterAttribute>();

展示拿起物体/放下物体的动画:

 public void ShowCarriedItem(int itemCode){ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(itemCode);if(itemDetails != null){equippedItemSpriteRenderer.sprite = itemDetails.itemSprite;equippedItemSpriteRenderer.color = new Color(1f, 1f, 1f, 1f);// Apply 'carry' character arms customisationarmsCharacterAttribute.partVariantType = PartVariantType.carry;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(armsCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);isCarrying = true;}}public void ClearCarriedItem(){equippedItemSpriteRenderer.sprite = null;equippedItemSpriteRenderer.color = new Color(1f, 1f, 1f, 0f);// Apply base character arms customisationarmsCharacterAttribute.partVariantType = PartVariantType.none;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(armsCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);isCarrying = false;}

完整的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : SingletonMonobehaviour<Player>
{private AnimationOverrides animationOverrides;  // 动画重写控制器private List<CharacterAttribute> characterAttributeCustomisationList;  // 目标动作列表[Tooltip("Should be populated in the prefab with the equippped item sprite renderer")][SerializeField] private SpriteRenderer equippedItemSpriteRenderer = null; // 武器的图片// Player attributes that can be swappedprivate CharacterAttribute armsCharacterAttribute;private CharacterAttribute toolCharacterAttribute;private float xInput;private float yInput;private bool isWalking;private bool isRunning;private bool isIdle;private bool isCarrying = false;private ToolEffect toolEffect = ToolEffect.none;private bool isUsingToolRight;private bool isUsingToolLeft;private bool isUsingToolUp;private bool isUsingToolDown;private bool isLiftingToolRight;private bool isLiftingToolLeft;private bool isLiftingToolUp;private bool isLiftingToolDown;private bool isPickingRight;private bool isPickingLeft;private bool isPickingUp;private bool isPickingDown;private bool isSwingToolRight;private bool isSwingToolLeft;private bool isSwingToolUp;private bool isSwingToolDown;private Camera mainCamera;private Rigidbody2D rigidbody2D;private Direction playerDirection;private float movementSpeed;private bool _playerInputIsDisabled = false;public bool PlayerInputIsDisabled { get => _playerInputIsDisabled; set => _playerInputIsDisabled = value; }protected override void Awake(){base.Awake();rigidbody2D = GetComponent<Rigidbody2D>();animationOverrides = GetComponentInChildren<AnimationOverrides>();// Initialise swappable character attributesarmsCharacterAttribute = new CharacterAttribute(CharacterPartAnimator.arms, PartVariantColour.none, PartVariantType.none);// Initialise character attribute listcharacterAttributeCustomisationList = new List<CharacterAttribute>();mainCamera = Camera.main;}private void Update(){#region  Player Inputif (!PlayerInputIsDisabled){ResetAnimationTrigger();PlayerMovementInput();PlayerWalkInput();// Send event to any listeners for player movement inputEventHandler.CallMovementEvent(xInput, yInput, isWalking, isRunning, isIdle, isCarrying, toolEffect,isUsingToolRight, isUsingToolLeft, isUsingToolUp, isUsingToolDown,isLiftingToolRight, isLiftingToolLeft, isLiftingToolUp, isLiftingToolDown,isPickingRight, isPickingLeft, isPickingUp, isPickingDown,isSwingToolRight, isSwingToolLeft, isSwingToolUp, isSwingToolDown,false, false, false, false);}#endregion Player Input}private void FixedUpdate(){PlayerMovement();}/// <summary>/// 展示拿东西的动画/// </summary>/// <param name="itemCode"></param>public void ShowCarriedItem(int itemCode){ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(itemCode);if(itemDetails != null){equippedItemSpriteRenderer.sprite = itemDetails.itemSprite;equippedItemSpriteRenderer.color = new Color(1f, 1f, 1f, 1f);// Apply 'carry' character arms customisationarmsCharacterAttribute.partVariantType = PartVariantType.carry;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(armsCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);isCarrying = true;}}public void ClearCarriedItem(){equippedItemSpriteRenderer.sprite = null;equippedItemSpriteRenderer.color = new Color(1f, 1f, 1f, 0f);// Apply base character arms customisationarmsCharacterAttribute.partVariantType = PartVariantType.none;characterAttributeCustomisationList.Clear();characterAttributeCustomisationList.Add(armsCharacterAttribute);animationOverrides.ApplyCharacterCustomisationParameters(characterAttributeCustomisationList);isCarrying = false;}private void PlayerMovement(){Vector2 move = new Vector2(xInput * movementSpeed * Time.deltaTime, yInput * movementSpeed * Time.deltaTime);rigidbody2D.MovePosition(rigidbody2D.position + move);}private void ResetAnimationTrigger(){toolEffect = ToolEffect.none;isUsingToolRight = false;isUsingToolLeft = false;isUsingToolUp = false;isUsingToolDown = false;isLiftingToolRight = false;isLiftingToolLeft = false;isLiftingToolUp = false;isLiftingToolDown = false;isPickingRight = false;isPickingLeft = false;isPickingUp = false;isPickingDown = false;isSwingToolRight = false;isSwingToolLeft = false;isSwingToolUp = false;isSwingToolDown = false;}private void PlayerMovementInput(){xInput = Input.GetAxisRaw("Horizontal");yInput = Input.GetAxisRaw("Vertical");// 斜着移动if (xInput != 0 && yInput != 0) {xInput = xInput * 0.71f;yInput = yInput * 0.71f;}// 在移动if (xInput != 0 || yInput != 0) {isRunning = true;isWalking = false;isIdle = false;movementSpeed = Settings.runningSpeed;// Capture player direction for save gameif (xInput < 0){playerDirection = Direction.left;}else if (xInput > 0){playerDirection = Direction.right;}else if (yInput < 0){playerDirection = Direction.down;}else{playerDirection = Direction.up;}}else if(xInput == 0 && yInput == 0){isRunning = false;isWalking = false;isIdle = true;}}// 按住Shift键移动为walkprivate void PlayerWalkInput(){if(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift)){isRunning = false;isWalking = true;isIdle = false;movementSpeed = Settings.walkingSpeed;}else{isRunning = true;isWalking = false;isIdle = false;movementSpeed = Settings.runningSpeed;}}public Vector3 GetPlayerViewportPosition(){// Vector3 viewport position for player (0,0) viewport bottom left, (1,1) viewport top rightreturn mainCamera.WorldToViewportPoint(gameObject.transform.position);}public void DisablePlayerInputAndResetMovement(){DisablePlayerInpupt();ResetMovement();// Send event to any listeners for player movement inputEventHandler.CallMovementEvent(xInput, yInput, isWalking, isRunning, isIdle, isCarrying, toolEffect,isUsingToolRight, isUsingToolLeft, isUsingToolUp, isUsingToolDown,isLiftingToolRight, isLiftingToolLeft, isLiftingToolUp, isLiftingToolDown,isPickingRight, isPickingLeft, isPickingUp, isPickingDown,isSwingToolRight, isSwingToolLeft, isSwingToolUp, isSwingToolDown,false, false, false, false);}private void ResetMovement(){// Reset movementxInput = 0f;yInput = 0f;isRunning = false;isWalking = false;isIdle = true;}public void DisablePlayerInpupt(){PlayerInputIsDisabled = true;}public void EnablePlayerInput(){PlayerInputIsDisabled = false;}
}

9、修改UIInventorySlot.cs脚本

在SetSelectedItem中新增如下代码:

if (itemDetails.canBeCarried == true)
{// Show player carrying itemPlayer.Instance.ShowCarriedItem(itemDetails.itemCode);
}
else 
{Player.Instance.ClearCarriedItem();
}

在ClearSelectedItem中新增如下代码:

// Clear player carrying item
Player.Instance.ClearCarriedItem();

完整的代码如下:

using UnityEngine;
using TMPro;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;public class UIInventorySlot : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{private Camera mainCamera;private Transform parentItem; // 场景中的物体父类private GameObject draggedItem; // 被拖动的物体private Canvas parentCanvas;public Image inventorySlotHighlight;public Image inventorySlotImage;public TextMeshProUGUI textMeshProUGUI;[SerializeField] private UIInventoryBar inventoryBar = null;[SerializeField] private GameObject itemPrefab = null;[SerializeField] private int slotNumber = 0; // 插槽的序列号[SerializeField] private GameObject inventoryTextBoxPrefab = null;[HideInInspector] public ItemDetails itemDetails;[HideInInspector] public int itemQuantity;[HideInInspector] public bool isSelected = false;private void Awake(){parentCanvas = GetComponentInParent<Canvas>();}private void Start(){mainCamera = Camera.main;parentItem = GameObject.FindGameObjectWithTag(Tags.ItemsParentTransform).transform;}public void OnBeginDrag(PointerEventData eventData){if(itemDetails != null) {// Disable keyboard inputPlayer.Instance.DisablePlayerInputAndResetMovement();// Instatiate gameobject as dragged itemdraggedItem = Instantiate(inventoryBar.inventoryBarDraggedItem, inventoryBar.transform);// Get image for dragged itemImage draggedItemImage = draggedItem.GetComponentInChildren<Image>();draggedItemImage.sprite = inventorySlotImage.sprite;SetSelectedItem();}}public void OnDrag(PointerEventData eventData){// move game object as dragged itemif(!draggedItem != null){draggedItem.transform.position = Input.mousePosition;}}public void OnEndDrag(PointerEventData eventData){// Destroy game object as dragged itemif (draggedItem != null) {Destroy(draggedItem);// if drag ends over inventory bar, get item drag is over and swap thenif (eventData.pointerCurrentRaycast.gameObject != null && eventData.pointerCurrentRaycast.gameObject.GetComponent<UIInventorySlot>() != null) {// get the slot number where the drag endedint toSlotNumber = eventData.pointerCurrentRaycast.gameObject.GetComponent<UIInventorySlot>().slotNumber;// Swap inventory items in inventory listInventoryManager.Instance.SwapInventoryItems(InventoryLocation.player, slotNumber, toSlotNumber);// Destroy inventory text boxDestroyInventoryTextBox();// Clear selected itemClearSelectedItem();}else{// else attemp to drop the item if it can be droppedif (itemDetails.canBeDropped){DropSelectedItemAtMousePosition();}}// Enable player inputPlayer.Instance.EnablePlayerInput();}}/// <summary>/// Drops the item(if selected) at the current mouse position. called by the DropItem event/// </summary>private void DropSelectedItemAtMousePosition(){if(itemDetails != null && isSelected){Vector3 worldPosition = mainCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, -mainCamera.transform.position.z));// Create item from prefab at mouse positionGameObject itemGameObject = Instantiate(itemPrefab, worldPosition, Quaternion.identity, parentItem);Item item = itemGameObject.GetComponent<Item>();item.ItemCode = itemDetails.itemCode;// Remove item from player's inventoryInventoryManager.Instance.RemoveItem(InventoryLocation.player, item.ItemCode);// If no more of item then clear selectedif(InventoryManager.Instance.FindItemInInventory(InventoryLocation.player, item.ItemCode) == -1){ClearSelectedItem();}}}public void OnPointerEnter(PointerEventData eventData){// Populate text box with item detailsif(itemQuantity != 0){// Instantiate inventory text boxinventoryBar.inventoryTextBoxGameobject = Instantiate(inventoryTextBoxPrefab, transform.position, Quaternion.identity);inventoryBar.inventoryTextBoxGameobject.transform.SetParent(parentCanvas.transform, false);UIInventoryTextBox inventoryTextBox = inventoryBar.inventoryTextBoxGameobject.GetComponent<UIInventoryTextBox>();// Set item type descriptionstring itemTypeDescription = InventoryManager.Instance.GetItemTypeDescription(itemDetails.itemType);// Populate text boxinventoryTextBox.SetTextboxText(itemDetails.itemDescription, itemTypeDescription, "", itemDetails.itemLongDescription, "", "");// Set text box position according to inventory bar positionif (inventoryBar.IsInventoryBarPositionBottom){inventoryBar.inventoryTextBoxGameobject.GetComponent<RectTransform>().pivot = new Vector2(0.5f, 0f);inventoryBar.inventoryTextBoxGameobject.transform.position = new Vector3(transform.position.x, transform.position.y + 50f, transform.position.z);}else{inventoryBar.inventoryTextBoxGameobject.GetComponent<RectTransform>().pivot = new Vector2(0.5f, 1f);inventoryBar.inventoryTextBoxGameobject.transform.position = new Vector3(transform.position.x, transform.position.y - 50f, transform.position.z);}}}public void OnPointerExit(PointerEventData eventData){DestroyInventoryTextBox();}private void DestroyInventoryTextBox(){if (inventoryBar.inventoryTextBoxGameobject != null) {Destroy(inventoryBar.inventoryTextBoxGameobject);}}public void OnPointerClick(PointerEventData eventData){// if left clickif (eventData.button == PointerEventData.InputButton.Left){// if inventory slot currently selected then deselectif (isSelected == true){ClearSelectedItem();}else  // 未被选中且有东西则显示选中的效果{if(itemQuantity > 0){SetSelectedItem();}}}}/// <summary>/// Set this inventory slot item to be selected/// </summary>private void SetSelectedItem(){// Clear currently highlighted itemsinventoryBar.ClearHighlightOnInventorySlots();// Highlight item on inventory barisSelected = true;// Set highlighted inventory slotsinventoryBar.SetHighlightedInventorySlots();// Set item selected in inventoryInventoryManager.Instance.SetSelectedInventoryItem(InventoryLocation.player, itemDetails.itemCode);if (itemDetails.canBeCarried == true){// Show player carrying itemPlayer.Instance.ShowCarriedItem(itemDetails.itemCode);}else {Player.Instance.ClearCarriedItem();}}private void ClearSelectedItem(){// Clear currently highlighted iteminventoryBar.ClearHighlightOnInventorySlots();isSelected = false;// set no item selected in inventoryInventoryManager.Instance.ClearSelectedInventoryItem(InventoryLocation.player);// Clear player carrying itemPlayer.Instance.ClearCarriedItem();}
}

10、创建对象/资源

(1)创建动画描述资源

在Assets -> Scriptable Object Assets下创建Animation目录。

在其下再新建Animation Types的目录,在其下再创建arms的目录,在其下再创建NoneCarry(partVariantColour=None, partVariantType=Carry)和NoneNone的目录。

新建动画描述示例:

创建的内容罗列如下:其中NoneCarryxxx的放在NoneCarry目录下,NoneNonexxx的放在NoneNone目录下。

NameAnimation ClipAnimation NameCharacter PartPart Variant ColourPart Variant Type
ArmsNoneCarryIdleDownArmsNoneCarryIdleDownIdle DownArmsNoneCarry
ArmsNoneCarryIdleLeftArmsNoneCarryIdleLeftIdle LeftArmsNoneCarry
ArmsNoneCarryIdleRightArmsNoneCarryIdleRightIdle RightArmsNoneCarry
ArmsNoneCarryIdleUpArmsNoneCarryIdleUpIdle UpArmsNoneCarry
ArmsNoneCarryRunDownArmsNoneCarryRunDownRun DownArmsNoneCarry
ArmsNoneCarryRunLeftArmsNoneCarryRunLeftRun LeftArmsNoneCarry
ArmsNoneCarryRunRightArmsNoneCarryRunRightRun RightArmsNoneCarry
ArmsNoneCarryRunUpArmsNoneCarryRunUpRun UpArmsNoneCarry
ArmsNoneCarryWalkDownArmsNoneCarryWalkDownWalk DownArmsNoneCarry
ArmsNoneCarryWalkLeftArmsNoneCarryWalkLeftWalk LeftArmsNoneCarry
ArmsNoneCarryWalkRightArmsNoneCarryWalkRightWalk RightArmsNoneCarry
ArmsNoneCarryWalkUpArmsNoneCarryWalkUpWalk UpArmsNoneCarry
ArmsNoneNoneIdleDownArmsNoneNoneIdleDownIdle DownArmsNoneNone
ArmsNoneNoneIdleLeftArmsNoneNoneIdleLeftIdle LeftArmsNoneNone
ArmsNoneNoneIdleRightArmsNoneNoneIdleRightIdle RightArmsNoneNone
ArmsNoneNoneIdleUpArmsNoneNoneIdleUpIdle UpArmsNoneNone
ArmsNoneNoneRunDownArmsNoneNoneRunDownRun DownArmsNoneNone
ArmsNoneNoneRunLeftArmsNoneNoneRunLeftRun LeftArmsNoneNone
ArmsNoneNoneRunRightArmsNoneNoneRunRightRun RightArmsNoneNone
ArmsNoneNoneRunUpArmsNoneNoneRunUpRun UpArmsNoneNone
ArmsNoneNoneWalkDownArmsNoneNoneWalkDownWalk DownArmsNoneNone
ArmsNoneNoneWalkLeftArmsNoneNoneWalkLeftWalk LeftArmsNoneNone
ArmsNoneNoneWalkRightArmsNoneNoneWalkRightWalk RightArmsNoneNone
ArmsNoneNoneWalkUpArmsNoneNoneWalkUpWalk UpArmsNoneNone

(2)创建动画重写控制器物体

在Hierarchy -> Player下创建新物体命名为CharacterCustomiser。

添加Animation Overriders组件。

(3)修改equippedItem对象

修改position y 为1.5。

(4)Player对象设置equip对象

运行程序,效果如下:

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词