麦田物语第十四天

系列文章目录

麦田物语第十四天



前言

昨天制作了人物的移动(利用混合树),然后发现人物移动时的动画出问题了,所以今天先查找出问题的原因,我先把Arm和Body的动画重新做了一遍,结果发现还是相同的问题,最后问了大佬发现原来是混合树的Parameters设置错了,都给设置成InputX了,改正后就开始了今天的项目总结。


一、实现选中物品触发举起动画

本小节我们想要实现的功能是点击背包中的物品人物就会举起物品,并且学习了这个方法之后我们也可以实现人物使用工具,更换衣服等功能。
因为我们要举起物体,因此在Player下创建一个空物体HoldItem并添加Sprite Renderer组件,同时调整渲染方式(Sprite Sort Point)为Povit,渲染层级(Sorting Layer)为Instance,并更改层级顺序(Order In Layer)为2,避免头发出现在该物体的前面;接着调整该物体到合适位置,最后禁用其Sprite Renderer组件。
当我们举起物品时,只需要实现的是手臂动画的切换,所以我们通过代码来实现Animator Override的更换:
首先创建Scripts-> Player -> AnimatorOverride脚本,在这个脚本中需要拿到所有的 Animator 组件和 HoldItem的Sprite Renderer组件;并在Awake方法中获取Animators,我们就可以返回Unity进行拖拽赋值了。
因为我们想要实现手臂动画的切换,那么需要制作出来当玩家举起物体时的手臂动画,也上节一样,我们需要创建Animator Override Controller,并将Base Controller赋值给它,接着将需要的动画添加上去即可(这些动画都在文件夹中,也可自己制作)。
接下来我们就要实现切换动画的逻辑了。
首先我们需要实现的就是通过点击物品的类型实现相应的逻辑从而实现动画切换,那我们需要实现字典的方式是Player身体的各个部位的Animator匹配想要的部件和物品的ID等相关的信息。
接下来我们需要创建一些新的枚举类型,首先是PartType,表示这个物体的功能类型是什么;

PartType的枚举代码如下:

public enum PartType
{
    None,Carry,Hoe,Break
}

接下来需要创建的是PartName,枚举出我们身体的各个位置;

PartName的枚举代码如下:

public enum PartName
{
    Body,Hair,Arm,Tool
}

相信看到这个我们就能发现这些类型的作用了,我们根据物品的类型从而切换身体的不同部分的动画,然后我们来具体看看代码怎么写:
我们刚才所说的逻辑需要存储下来,因此返回DataCollection脚本,编写一个新的类型AnimatorType,记得需要序列化,在该类型中我们首先需要PartType类型的变量来存储物品功能,PartName类型的变量来存储身体部位,以及最重要的需要使用的Animator Override Controller,表名要切换那个Animator。

DataCollection脚本的AnimatorType类型代码如下:

[System.Serializable]
public class AnimatorType
{
    public PartType partType;
    public PartName partName;
    public AnimatorOverrideController overrideController;
}

接着我们就可以回到AnimatorOverride脚本中定义AnimatorType列表,返回Unity对其进行赋值,大致如下:
在这里插入图片描述
我们还需要编写字典来存储身体的每个部位对应的Animator,将Animator的名字和Animator本身存入这个字典中。那么怎么生成这个字典呢,我们只需要遍历一遍animators数组,然后将其名字和本身存入字典即可。
当我们点击Slot_UI上的物品时,才会进行这个切换,在切换时我们需要传递物品的信息从而对HoldItem的Sprite Renderer组件赋值,所以我们仍然采取呼叫的方式来编写这个方法。(单击选中,再次单击取消选中)

EventHandler脚本的ItemSelectEvent代码如下

public static event Action<ItemDetails, bool> ItemSelectedEvent;
    public static void CallItemSelectedEvent(ItemDetails itemDetails, bool isSelected)
    {
        ItemSelectedEvent?.Invoke(itemDetails, isSelected);
    }

接下来我们在点选物品的方法OnPointerClick中发送这个呼叫,并且只有在背包中点选物品时才会发送(在商店中的物品我们无法使用)。

SlotUI的OnPointerClick方法如下:

public void OnPointerClick(PointerEventData eventData)
        {
            if (itemAmount == 0) return;
            isSelected = !isSelected;
            inventoryUI.UpdateSlotHightlight(slotIndex);

            if (slotType == SlotType.Bag)
            {
                //通知物品被选中的状态和信息
                EventHandler.CallItemSelectedEvent(itemDetails, isSelected);
            }
        }

接下来返回AnimatorOverride脚本中,编写OnEnable和OnDisable方法,即添加和取消了OnItemSelectedEvent方法,首先我们通过语法糖来实现当前物品类型(ItemDetails)对应的PartType的什么类型currentType。我们目前想要实现的是将商品和种子视为可举起的类型,那么就先只编写这两个,剩下的之后在写即可(当我们添加新的工具之后一定会有新的动画,此时我们就需要将这个语法糖补充完整)。然后我们编写新的方法SwitchAnimator通过currentType实现动画的切换,在SwitchAnimator方法中我们先要遍历AnimatorType列表,如果某一项的PartType刚好等于currentType,此时我们就要切换动画,那么我们怎么切换动画嘞?
还记得当时定义的字典嘛,我们可以使用AnimatorType列表中的PartName匹配到字典中的Animator组件,并切换该组件的AnimatorController为AnimatorType列表中的override Controller。
我们还需要调用这个方法,但是调用这个方法前我们还需要对是否选择了该物体的bool值进行判断,如果该物体没有被选择,将currentType赋值为PartType.None,并且将holdItem设置为未激活状态;如果该物体被选择的话,那么将ItemDetails的itemOnWorldSprite赋值给holdItem的Sprite Renderer,同时激活HoldItem即可。

AnimatorOverride脚本代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AnimatorOverride : MonoBehaviour
{
private Animator[] animators;
public SpriteRenderer holdItem;

[Header("各部分动画列表")]
public List<AnimatorType> animatorTypes;

private Dictionary<string, Animator> animatorNameDict = new Dictionary<string, Animator>();

private void Awake()
{
    animators = GetComponentsInChildren<Animator>();

    foreach (var anim in animators)
    {
        animatorNameDict.Add(anim.name, anim);
    }
}

private void OnEnable()
{
    EventHandler.ItemSelectedEvent += OnItemSelectedEvent;
}


private void OnDisable()
{
    EventHandler.ItemSelectedEvent -= OnItemSelectedEvent;
}

private void OnItemSelectedEvent(ItemDetails itemDetails, bool isSelected)
{
    //WORKFLOW:不同的工具返回不同的动画在这里补全
    //语法糖
    PartType currentType = itemDetails.itemType switch
    {
        ItemType.Seed => PartType.Carry,
        ItemType.Commodity => PartType.Carry,
        _=> PartType.None
    };

    if (isSelected == false)
    {
        currentType = PartType.None;
        holdItem.enabled = false;
    }
    else
    {
        if (currentType == PartType.Carry)
        {
            holdItem.sprite = itemDetails.itemOnWorldSprite;
            holdItem.enabled = true;
        }
    }

    SwitchAnimator(currentType);
}

private void SwitchAnimator(PartType partType)
{
    foreach(var item in animatorTypes)
    {
        if (item.partType == partType)
        {
            animatorNameDict[item.partName.ToString()].runtimeAnimatorController = item.overrideController;
        }
    }
}

}

二、绘制房子和可以被砍伐的树

本小节我们将我们的场景丰富一些。
首先先进行房子的绘制(绘制步骤我忘了,所以返回之前的文章重新复习了一遍)。过程如下:首先点击Tile Palette,然后创建新的Palette(TileMaps文件夹-> Palettes),接着将房子的图片拖入新建的Palette,这些图片存放在TileMap文件夹->Tiles中,然后选择除了房顶外的部分并且选择Active Tilemap为Ground Top,然后在地图中进行绘制,接着将房顶绘制在Front1层中,这样就会完全遮盖Player。
接着我们要为房子画上碰撞体,切换至Collision的Palette,然后选择Active Tilemap为Collision,并将01.Field场景中的Collision物体身上的Tilemap Renderer激活,这样我们绘制的碰撞体就可以在地图上看到了,方便绘制(我们绘制完成后关闭即可)。

我绘制的房子碰撞体如下

在这里插入图片描述
接着我们制作可以被砍倒的树,首先需在M_Studio->Art->Items->Tree01和Tree02,我们制作一个,另一个同理即可。
首先将Tree01_Bottom拖入场景,然后更改其渲染方式为Povit,更改层级为Instance,同理也将Tree01_Top也拖入场景,将其层级也改为Instance,同时层序为1,这样确保了树叶可以在树根上面显示,接着创建一个空物体改名为Tree01,然后将其位置与Buttom位置设置为相同的,并将Bottom和Top拖入作为其子物体,接着给该空物体添加Sorting Group组件,将其层级也设置为Instance,再添加Box Collider 2D,设置其大小,勾选Is Trigger,给其子物体都添加ItemFade脚本,最后在给Bottom添加Box Collider 2D并设置其大小。
最后将树拖拽至Prefab->Tree文件夹中作为预制体。

Tree的Box Collider 2D的大小设置如下:

在这里插入图片描述

  • 21
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
麦田里的守望者》是美国作家J.D. Salinger所著的小说,该小说于1951年出版。该小说以第一人称叙述的方式,讲述了一位名叫霍尔顿·考尔菲尔德的十六岁男孩的故事,他在美国东部的一所寄宿学校度过了一个寒假。小说通过霍尔顿的视角,描绘了他的思想、情感和经历,反映了他对社会、人性和成长的认识与探索。 在近年来的研究中,学者们主要从以下几个方面对《麦田里的守望者》进行了文献综述: 1. 霍尔顿的反叛心理。许多学者探讨了霍尔顿的反叛心理,认为他的反叛是对社会价值观的质疑和对现实生活的不满。他试图保持自己的纯真和真实,而对于社会的虚伪和不公,他感到无法接受。 2. 霍尔顿的孤独与心理问题。一些学者认为,霍尔顿的孤独和心理问题是导致他反叛的原因之一。他对周围的人和事都持怀疑态度,感到难以融入社会。同时,他也存在着一些心理问题,如焦虑、抑郁等,这些问题影响着他的生活和行为。 3. 霍尔顿的成长与人性观。还有一些学者认为,霍尔顿的故事是一种成长与人性探索的过程。他在寻找自己的价值观和人生意义的过程中,经历了一系列的挫折和成长。他逐渐认识到人性的复杂性和社会的不完美性,也逐渐接受了自己的缺点和弱点。 4. 《麦田里的守望者》的文学价值。这部小说被认为是现代文学的经典之作,因为它深入地揭示了人类内心的复杂性和社会的种种问题。它的语言简洁、生动,情节紧凑,给人留下了深刻的印象。 综上所述,《麦田里的守望者》是一部充满探索与思考的小说,它通过一个十六岁男孩的视角,反映了现代社会中普遍存在的问题,也引发了人们对于成长、人性和社会的深入思考。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值