当前位置: 首页 > news >正文

胡闹厨房练习(三)

ScriptableObject

一、初步了解

1、实质:是一种特殊类型的Unity对象,

2、作用:用于存储大量数据,而不必依附于游戏场景中的某个GameObject。

3、特点:

可以在不增加场景中对象数量的情况下,管理和存储复杂的数据结构、配置信息、游戏状态等。

4、适用:非常适合用来管理游戏中的各种数据,如角色属性、关卡配置、道具列表等。

5、意义:

使数据的管理更加集中和高效,避免将大量数据直接硬编码在脚本中或在多个GameObject上重复配置相同的数据。

还可以用于实现游戏数据的序列化,方便在游戏运行时保存和加载游戏状态。

二、创建方法

创建一个ScriptableObject.cs,名字自取,例如

using UnityEngine;[CreateAssetMenu(fileName = "NewItem", menuName = "Inventory/Item")]
public class Item : ScriptableObject
{public new string name;public Sprite icon = null;public string description = "";public int value;
}
三、使用方法

1、在Unity编辑器中通过CreateAssetMenu定义的菜单项创建ScriptableObject实例

2、在其他脚本中,通过Resources.Load<T>()或其他方式加载这个ScriptableObject实例,并使用它的属性,例如

Item myItem = Resources.Load<Item>("Path/To/Your/Item");
Debug.Log(myItem.name);

菜单管理

一、食谱

1、食谱名称和食谱成分:在Scripts/ScriptableObject文件夹下,新建RecipeSO.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu()]
public class RecipeSO : ScriptableObject
{public List<KitchenObjectSO> kitchenObjectSOList;public string recipeName;
}

2、在ScriptableObjects文件夹下,新建RecipeSO文件夹

3、新建RecipeSO对象:Burger

3、复制Burger,重命名为Cheeseburger,更改名称、添加CheeseSlicesSO(如上图)

4、同样的方法制作RecipeSO对象:MEGAburger、Salad

二、菜单

1、菜单列表:

(1) 在Scripts/ScriptableObjects中新建RecipeListSO.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu()]
public class RecipeListSO : ScriptableObject
{public List<RecipeSO> recipeSOList;
}

 (2) 创建RecipeListSO对象,命名为_RecipeListSO,设置菜单

2、取消创建项:编辑RecipeListSO.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//[CreateAssetMenu()]
public class RecipeListSO : ScriptableObject
{public List<RecipeSO> recipeSOList;
}
三、订单

1、Create Empty,命名为DeliveryManager,Reset它的Transform

2、随机订单:为DeliveryManager添加DeliveryManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DeliveryManager : MonoBehaviour
{[SerializeField] private RecipeListSO recipeListSO;private List<RecipeSO> waitingRecipeSOList;private float spawnRecipeTimer;private float spawnRecipeTimeMax = 4f;private int waitingRecipesMax = 4;private void Awake(){waitingRecipeSOList = new List<RecipeSO>();}private void Update(){// 时间计时器spawnRecipeTimer -= Time.deltaTime;// 检查倒计时是否结束‌if (spawnRecipeTimer <= 0f){// 当倒计时结束时,将spawnRecipeTimer重置为spawnRecipeTimeMaxspawnRecipeTimer = spawnRecipeTimeMax;if (waitingRecipeSOList.Count < waitingRecipesMax){// 随机选择食谱并添加到等待列表‌RecipeSO waitingRecipeSO = recipeListSO.recipeSOList[Random.Range(0, recipeListSO.recipeSOList.Count)];// 在控制台打印出所选食谱的名称Debug.Log(waitingRecipeSO.recipeName);waitingRecipeSOList.Add(waitingRecipeSO);}}}
}

3、检查玩家提交食品与订单是否匹配

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DeliveryManager : MonoBehaviour
{public static DeliveryManager Instance { get; private set; }[SerializeField] private RecipeListSO recipeListSO;private List<RecipeSO> waitingRecipeSOList;private float spawnRecipeTimer;private float spawnRecipeTimeMax = 4f;private int waitingRecipesMax = 4;private void Awake(){Instance = this;waitingRecipeSOList = new List<RecipeSO>();}private void Update(){spawnRecipeTimer -= Time.deltaTime;if (spawnRecipeTimer <= 0f){spawnRecipeTimer = spawnRecipeTimeMax;if (waitingRecipeSOList.Count < waitingRecipesMax){RecipeSO waitingRecipeSO = recipeListSO.recipeSOList[Random.Range(0, recipeListSO.recipeSOList.Count)];Debug.Log(waitingRecipeSO.recipeName);waitingRecipeSOList.Add(waitingRecipeSO);}}}// 检查玩家提交食品是否与订单相匹配的方法public void DeliverRecipe(PlateKitchenObject plateKitchenObject){// 遍历订单列表中的每一个订单for (int i = 0; i < waitingRecipeSOList.Count; i++){// 获取一个订单RecipeSO waitingRecipeSO = waitingRecipeSOList[i];// 检查食材数量与订单数量是否匹配if (waitingRecipeSO.kitchenObjectSOList.Count == plateKitchenObject.GetKitchenObjectsSOList().Count){// Has the same number of ingredientsbool plateContentsMatchesRecipe = true;// 遍历订单中的每一个食材foreach (KitchenObjectSO recipeKitchenObjectSO in waitingRecipeSO.kitchenObjectSOList){// Cycling through all ingredients in the Recipe// 初始化一个标志,用于表示是否在当前盘子上找到了食谱中的食材bool ingredientFound = false;// 遍历盘子上的每一个食材foreach (KitchenObjectSO plateKitchenObjectSO in plateKitchenObject.GetKitchenObjectsSOList()){// Cycling through all ingredients in the plate// 如果盘子上的食材与订单中的食材相同if (plateKitchenObjectSO == recipeKitchenObjectSO){// Ingredients matches!// 设置标志为true,表示找到了食材ingredientFound = true;// 跳出内层循环,因为已经找到了匹配的食材break;}}// 如果在当前盘子上没有找到食谱中的这个食材if (!ingredientFound){// This Recipe ingredient was not found on the plate// 设置盘子与食谱不匹配的标志plateContentsMatchesRecipe = false;}}// 如果盘子与食谱匹配if (plateContentsMatchesRecipe){// Player delivered the correct recipe!// 在控制台打印消息表示玩家提交了正确的食谱Debug.Log("Player delivered the correct recipe!");// 从订单列表中移除这个食谱waitingRecipeSOList.RemoveAt(i);// 退出方法,因为已经找到了匹配的食谱return;}}}// No matches found! 遍历完订单列表后没有找到匹配的食谱// Player did not deliver a correct recipe在控制台打印消息表示玩家没有提交正确的食谱Debug.Log("Player did not deliver a correct recipe!");}
}

关于if(){}

bool a  = false;if(a){Debug.Log("如果a为true,则输出文字。");}//这段代码不会被执行,因为不符合条件
bool a  = false;if(!a){Debug.Log("如果!a为true,则输出文字。");}//这段代码会被执行
// 因为a = false,那么!a的结果为true

4、编辑DeliveryCounter.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DeliveryCounter : BaseCounter
{public override void Interact(Player player){if (player.HasKitchenObject()){if (player.GetKitchenObject().TryGetPlate(out PlateKitchenObject plateKitchenObject)){// Only accepts PlatesDeliveryManager.Instance.DeliverRecipe(plateKitchenObject);player.GetKitchenObject().DestroySelf();}}}
}
四、订单面板

1、新建并设置Hierarchy面板上的Canvas

(1) 打开Inspector面板,将Canvas下的Render Mode 设置为Screen Space - Overlay,

(2) Canvas Scaler 中UI Scale Mode 设置为Scale With Screen Size,

(3) Reference Resolution 中x = 1920,y = 1080。

(4) Match=1(完全匹配高度)

设置结果:Canvas上的UI在游戏窗口宽度改变时不会改变,在高度改变时会等比例缩小,

设置目的:只关心UI的横向排布,而当纵向改变时该组件会自动缩放

2、UI-Image,设置Image的Color 为 FF0000,删除此Image

3、打开Game界面,设置为Full HD(1920*1080),可见红色图标

4、订单UI面板

(1) 以Canvas为父物体,Create Empty,命名为DeliveryManagerUI

(2) 设置面板:Alt+Stretch,Left、Top、Right、Bottom都为0。

此时,DeliveryManagerUI填满整个Canvas

五、订单内容

1、订单UI文本

(1) 以DeliveryManagerUI为父物体,UI-Text(TMP),重命名为TitleText。

(2) 文本为“RECIPES WAITING...”,字体设置为加粗(Bold)

(3) 将锚点设置到左上角,Width和Hight都为0,Wrapping设为Disabled,

(4) 移动到合适位置,posX = 33,PosY = -16

2、单个订单背景:

(1) 以DeliveryManagerUI 为父物体,Create Empty,命名为Container

(2) 锚点左上角,调整位置 Pos.x = 29,Pos.y=-91,Width和Hight都为0

(3) 给Container添加Vertical Layout Group组件,Padding下间距(Spacing)为30

3、单个订单图标模板

(1) Container下Create Empty,命名为RecipeTemplate,

(2) 选中RecipeTemplate,Shift +选择左上角图标,设置Width和Height分别为250,100

(3) 以RecipeTemplate为父物体,UI- Image,命名为Background,Alt + Stretch

(4) 颜色为黑色,透明度233

4、单个订单名称

(1) 以RecipeTemplate为父物体,UI- Text(TMP),命名为RecipeNameText

(2) 字号为20,加粗,Width、Hight都为0,Wrapping设为Disabled,文本内容为Recipe,白色

(3) 锚点左上,Pos.x = 10 ,Pos.y = -5

5、复制两个RecipeTemplate

6、编辑DeliveryManager.cs

public List<RecipeSO> GetKitchenObjectsSOList()
{return waitingRecipeSOList;
}

7、显示订单图标:给DeliveryManagerUI添加DeliveryManagerUI.cs组件 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DeliveryManagerUI : MonoBehaviour
{[SerializeField] private Transform container;[SerializeField] private Transform recipeTemplate;private void Awake(){recipeTemplate.gameObject.SetActive(false);}private void UpdateVisual(){// 清除UI界面上所有旧的订单图标foreach (Transform child in container){if(child == recipeTemplate) continue;//立即结束当前循环迭代Destroy(child.gameObject);}// 根据当前的订单列表创建并显示新的图标foreach (RecipeSO recipeSO in DeliveryManager.Instance.GetOrdersList()){Transform recipeTransform = Instantiate(recipeTemplate,container);recipeTransform.gameObject.SetActive(true);}}
}

8、重组代码

(1) 添加委托事件和触发事件程序:编辑 DeliveryManager.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DeliveryManager : MonoBehaviour
{public event EventHandler OnRecipeSpawned;public event EventHandler OnRecipeCompleted;public static DeliveryManager Instance { get; private set; }[SerializeField] private RecipeListSO recipeListSO;private List<RecipeSO> waitingRecipeSOList;private float spawnRecipeTimer;private float spawnRecipeTimeMax = 4f;private int waitingRecipesMax = 4;private void Awake(){Instance = this;waitingRecipeSOList = new List<RecipeSO>();}private void Update(){spawnRecipeTimer -= Time.deltaTime;if (spawnRecipeTimer <= 0f){spawnRecipeTimer = spawnRecipeTimeMax;if (waitingRecipeSOList.Count < waitingRecipesMax){RecipeSO waitingRecipeSO = recipeListSO.recipeSOList[UnityEngine.Random.Range(0, recipeListSO.recipeSOList.Count)];waitingRecipeSOList.Add(waitingRecipeSO);OnRecipeSpawned?.Invoke(this,EventArgs.Empty);}}}public void DeliverRecipe(PlateKitchenObject plateKitchenObject){for (int i = 0; i < waitingRecipeSOList.Count; i++){RecipeSO waitingRecipeSO = waitingRecipeSOList[i];if (waitingRecipeSO.kitchenObjectSOList.Count == plateKitchenObject.GetKitchenObjectsSOList().Count){// Has the same number of ingredientsbool plateContentsMatchesRecipe = true;foreach (KitchenObjectSO recipeKitchenObjectSO in waitingRecipeSO.kitchenObjectSOList){// Cycling through all ingredients in the Recipebool ingredientFound = false;foreach (KitchenObjectSO plateKitchenObjectSO in plateKitchenObject.GetKitchenObjectsSOList()){// Cycling through all ingredients in the plateif (plateKitchenObjectSO == recipeKitchenObjectSO){// Ingredients matches!ingredientFound = true;break;}}if (!ingredientFound){// This Recipe ingredient was not found on the plateplateContentsMatchesRecipe = false;}}if (plateContentsMatchesRecipe){// Player delivered the correct recipe!waitingRecipeSOList.RemoveAt(i);OnRecipeCompleted?.Invoke(this,EventArgs.Empty);return;}}}}public List<RecipeSO> GetWaitingRecipeSOList(){return waitingRecipeSOList;}
}

(2) 订阅事件和事件处理程序:编辑DeliveryManagerUI.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DeliveryManagerUI : MonoBehaviour
{[SerializeField] private Transform container;[SerializeField] private Transform recipeTemplate;private void Awake(){recipeTemplate.gameObject.SetActive(false);}private void Start(){DeliveryManager.Instance.OnRecipeSpawned += DeliveryManager_OnRecipeSpawned;DeliveryManager.Instance.OnRecipeCompleted += DeliveryManager_OnRecipeCompleted;UpdateVisul();}private void DeliveryManager_OnRecipeCompleted(object sender, System.EventArgs e){UpdateVisul();}private void DeliveryManager_OnRecipeSpawned(object sender, System.EventArgs e){UpdateVisul();}private void UpdateVisul(){foreach (Transform child in container){if (child == recipeTemplate) continue;Destroy(child.gameObject);}foreach (RecipeSO recipeSO in DeliveryManager.Instance.GetWaitingRecipeSOList()){Transform recipeTransform = Instantiate (recipeTemplate,container);recipeTransform.gameObject.SetActive(true);}}
}

(3) 赋值

9、获取订单上的文本

(1) 给RecipeTemplate添加 DeliveryManagerSingleUI.cs组件

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;public class DeliveryManagerSingleUI : MonoBehaviour
{[SerializeField] private TextMeshProUGUI recipeNameText;public void SetRecipeSO(RecipeSO recipeSO){recipeNameText.text = recipeSO.recipeName;}
}

(2) 赋值

10、组织脚本文件夹:在Scripts文件夹下新建文件夹,命名为UI

11、显示订单内容:编辑DeliveryManagerUI.cs

private void UpdateVisul()
{foreach (Transform child in container){if (child == recipeTemplate) continue;Destroy(child.gameObject);}foreach (RecipeSO recipeSO in DeliveryManager.Instance.GetWaitingRecipeSOList()){Transform recipeTransform = Instantiate (recipeTemplate,container);recipeTransform.gameObject.SetActive(true);recipeTransform.GetComponent<DeliveryManagerSingleUI>().SetRecipeSO(recipeSO);}
}

12、显示订单图标

(1) 以RecipeTemplate为父物体,Create Empty,命名为IconContainer,Pos.x = -110,Width和Height都为0

(2) 以IconContainer为父物体,UI - Image,命名为IconTemplate,Width和Height都为40、

(3) Source Image 为Bread

(4) 给IconContainer添加Horizontal Layout Group组件,可复制几个IconTemplate查看效果

(5) 显示订单图标:编辑DeliveryManagerSingleUI.cs

using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.UI;public class DeliveryManagerSingleUI : MonoBehaviour
{[SerializeField] private TextMeshProUGUI recipeNameText;[SerializeField] private Transform iconContainer;[SerializeField] private Transform iconTemplate;private void Awake(){iconTemplate.gameObject.SetActive(false);}public void SetRecipeSO(RecipeSO recipeSO){recipeNameText.text = recipeSO.recipeName;foreach (Transform child in iconContainer){if (child == iconTemplate) continue;Destroy(child.gameObject);}foreach (KitchenObjectSO kitchenObjectSO in recipeSO.kitchenObjectSOList){Transform iconTransform = Instantiate(iconTemplate, iconContainer);iconTransform.gameObject.SetActive(true);iconTransform.GetComponent<Image>().sprite = kitchenObjectSO.sprite;}}
}

赋值

测试结果:按订单制作食物,送到配送台后,食物消失,订单消失

声音

一、背景音乐

1、Create Empy,命名为MusicManager,Reset Transform

2、为MusicManager添加Audio Source组件

设置Audio Source下的AudioClip为Music

勾选Play On Awake,勾选Loop(循环)

Priority为0,Volume为0.5

3、确保Main Camera上有Audio Listener组件 

二、配送音效

1、音效对象

(1) 在Scripts/ScripatableObjects文件夹下新建AudioClipRefsSO.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu()]
public class AudioClipRefsSO : ScriptableObject
{public AudioClip[] chop;public AudioClip[] deliveryFail;public AudioClip[] deliverySuccess;public AudioClip[] footstep;public AudioClip[] objectDrop;public AudioClip[] objectPickup;public AudioClip[] trash;public AudioClip[] warning;public AudioClip stoveSizzle;
}

(2) 在ScriptableObjects文件夹,制作 AudioClipRefsSO对象,命名为AudioClipRefsSO

(3) 添加对应属性

2、在DeliveryManager.cs中,声明两个EventHandler委托事件

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DeliveryManager : MonoBehaviour
{public event EventHandler OnRecipeSpawned;public event EventHandler OnRecipeCompleted;// 委托事件public event EventHandler OnRecipeSuccess;public event EventHandler OnRecipeFailed;public static DeliveryManager Instance { get; private set; }[SerializeField] private RecipeListSO recipeListSO;private List<RecipeSO> waitingRecipeSOList;private float spawnRecipeTimer;private float spawnRecipeTimeMax = 4f;private int waitingRecipesMax = 4;private void Awake(){Instance = this;waitingRecipeSOList = new List<RecipeSO>();}private void Update(){spawnRecipeTimer -= Time.deltaTime;if (spawnRecipeTimer <= 0f){spawnRecipeTimer = spawnRecipeTimeMax;if (waitingRecipeSOList.Count < waitingRecipesMax){RecipeSO waitingRecipeSO = recipeListSO.recipeSOList[UnityEngine.Random.Range(0, recipeListSO.recipeSOList.Count)];waitingRecipeSOList.Add(waitingRecipeSO);OnRecipeSpawned?.Invoke(this,EventArgs.Empty);}}}public void DeliverRecipe(PlateKitchenObject plateKitchenObject){for (int i = 0; i < waitingRecipeSOList.Count; i++){RecipeSO waitingRecipeSO = waitingRecipeSOList[i];if (waitingRecipeSO.kitchenObjectSOList.Count == plateKitchenObject.GetKitchenObjectsSOList().Count){// Has the same number of ingredientsbool plateContentsMatchesRecipe = true;foreach (KitchenObjectSO recipeKitchenObjectSO in waitingRecipeSO.kitchenObjectSOList){// Cycling through all ingredients in the Recipebool ingredientFound = false;foreach (KitchenObjectSO plateKitchenObjectSO in plateKitchenObject.GetKitchenObjectsSOList()){// Cycling through all ingredients in the plateif (plateKitchenObjectSO == recipeKitchenObjectSO){// Ingredients matches!ingredientFound = true;break;}}if (!ingredientFound){// This Recipe ingredient was not found on the plateplateContentsMatchesRecipe = false;}}if (plateContentsMatchesRecipe){// Player delivered the correct recipe!waitingRecipeSOList.RemoveAt(i);OnRecipeCompleted?.Invoke(this,EventArgs.Empty);// 触发成功事件OnRecipeSuccess?.Invoke(this,EventArgs.Empty);return;}}}// 触发失败事件OnRecipeFailed?.Invoke(this,EventArgs.Empty);}public List<RecipeSO> GetWaitingRecipeSOList(){return waitingRecipeSOList;}
}

3、Create Empty,命名为SoundManager,Reset Transform

4、为SoundManager添加SoundManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SoundManager : MonoBehaviour
{[SerializeField] private AudioClipRefsSO audioClipRefsSO;private void Start(){DeliveryManager.Instance.OnRecipeSuccess += DeliveryManager_OnRecipeSuccess;DeliveryManager.Instance.OnRecipeFailed += DeliveryManager_OnRecipeFailed;}private void DeliveryManager_OnRecipeFailed(object sender, System.EventArgs e){PlaySound(audioClipRefsSO.deliveryFail,Camera.main.transform.position);}private void DeliveryManager_OnRecipeSuccess(object sender, System.EventArgs e){PlaySound(audioClipRefsSO.deliverySuccess, Camera.main.transform.position);}private void PlaySound(AudioClip[] audioClipArray ,Vector3 position,float volume = 1f){PlaySound(audioClipArray[Random.Range(0,audioClipArray.Length)],position,volume);}private void PlaySound(AudioClip audioClip ,Vector3 position,float volume = 1f){AudioSource.PlayClipAtPoint(audioClip,position,volume);}    
}

5、赋值

6、调节声音播放的位置:

(1) 编辑DeliveryCounter.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class DeliveryCounter : BaseCounter
{public static DeliveryCounter Instance {  get; private set; }private void Awake(){Instance = this;}public override void Interact(Player player){if (player.HasKitchenObject()){if (player.GetKitchenObject().TryGetPlate(out PlateKitchenObject plateKitchenObject)){// Only accepts PlatesDeliveryManager.Instance.DeliverRecipe(plateKitchenObject);player.GetKitchenObject().DestroySelf();}}}
}

(2) 编辑SoundManager.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SoundManager : MonoBehaviour
{[SerializeField] private AudioClipRefsSO audioClipRefsSO;private void Start(){DeliveryManager.Instance.OnRecipeSuccess += DeliveryManager_OnRecipeSuccess;DeliveryManager.Instance.OnRecipeFailed += DeliveryManager_OnRecipeFailed;}private void DeliveryManager_OnRecipeFailed(object sender, System.EventArgs e){DeliveryCounter deliveryCounter = DeliveryCounter.Instance;PlaySound(audioClipRefsSO.deliveryFail, deliveryCounter.transform.position);}private void DeliveryManager_OnRecipeSuccess(object sender, System.EventArgs e){DeliveryCounter deliveryCounter = DeliveryCounter.Instance;PlaySound(audioClipRefsSO.deliverySuccess, deliveryCounter.transform.position);}private void PlaySound(AudioClip[] audioClipArray ,Vector3 position,float volume = 1f){PlaySound(audioClipArray[Random.Range(0,audioClipArray.Length)],position,volume);}private void PlaySound(AudioClip audioClip ,Vector3 position,float volume = 1f){AudioSource.PlayClipAtPoint(audioClip,position,volume);}}
三、切菜音效

1、声明、触发委托(按F时播放音效):编辑CuttingCounter.cs

场景存在多个处理台,不能用配送台的单例模式。所以使用静态委托:

以便使多个 CuttingCounter 实例能够共享同一个事件响应逻辑(共享OnAnyCut事件)

public static event EventHandler OnAnyCut;
public override void InteractAlternate(Player player)
{if (HasKitchenObject() && HasRecipeWithInput(GetKitchenObject().GetKitchenObjectSO())){cuttingProgress++;Oncut?.Invoke(this, EventArgs.Empty);OnAnyCut?.Invoke(this, EventArgs.Empty);}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;public class CuttingCounter : BaseCounter, IHasProgress
{public static event EventHandler OnAnyCut;public event EventHandler<IHasProgress.OnprogressChangedEventArgs> OnProgressChanged;public event EventHandler Oncut;[SerializeField] private CuttingRecipeSO[] cuttingRecipeSOArray;private int cuttingProgress;public override void Interact(Player player){if (!HasKitchenObject()){// There is no KitchenObject hereif (player.HasKitchenObject()){// player is carrying somethingif (HasRecipeWithInput(player.GetKitchenObject().GetKitchenObjectSO())){// Player carrying something that can be cutplayer.GetKitchenObject().SetKitchenObjectParent(this);cuttingProgress = 0;// CuttingRecipeSO cuttingRecipeSO = GetCuttingRecipeSOWithInput(GetKitchenObject().GetKitchenObjectSO());OnProgressChanged?.Invoke(this, new IHasProgress.OnprogressChangedEventArgs{progressNormalized = (float)cuttingProgress / cuttingRecipeSO.cuttingProgressMax});}}else{// Player not carrying anything}}else{// There is a KitchenObject hereif (player.HasKitchenObject()){// Player is carrying somethingif (player.GetKitchenObject().TryGetPlate(out PlateKitchenObject plateKitchenObject)){// Player is holding a Plateif (plateKitchenObject.TryAddIngredient(GetKitchenObject().GetKitchenObjectSO())){GetKitchenObject().DestroySelf();}}}else{// Player is not carrying anythingGetKitchenObject().SetKitchenObjectParent(player);}}}public override void InteractAlternate(Player player){if (HasKitchenObject() && HasRecipeWithInput(GetKitchenObject().GetKitchenObjectSO())){// There is a KitchenObject her and it can be cutcuttingProgress++;Oncut?.Invoke(this, EventArgs.Empty);OnAnyCut?.Invoke(this, EventArgs.Empty);CuttingRecipeSO cuttingRecipeSO = GetCuttingRecipeSOWithInput(GetKitchenObject().GetKitchenObjectSO());OnProgressChanged?.Invoke(this, new IHasProgress.OnprogressChangedEventArgs

相关文章:

胡闹厨房练习(三)

ScriptableObject 一、初步了解 1、实质:是一种特殊类型的Unity对象, 2、作用:用于存储大量数据,而不必依附于游戏场景中的某个GameObject。 3、特点: 可以在不增加场景中对象数量的情况下,管理和存储复杂的数据结构、配置信息、游戏状态等。 4、适用:非常适合用来…...

关于ESD(静电放电)等级的划分

关于ESD&#xff08;静电放电&#xff09;等级的划分&#xff0c;主要依据不同的测试模型和测试标准。以下是对HBM&#xff08;人体模型&#xff09;和CDM&#xff08;充电器件模型&#xff09;两种测试模型下ESD等级划分的详细解释&#xff1a; HBM ESD等级划分 HBM ESD等级…...

探究步进电机与输入脉冲的关系

深入了解步进电机 前言一、 步进电机原理二、 细分三、脉冲数总结 前言 主要是探究以下内容&#xff1a; 1、步进电机的步进角。 2、什么是细分。 3、脉冲的计算。 最后再扩展以下STM32定时器的计算方法。 一、 步进电机原理 其实语言描述怎么样都不直观&#xff0c;我更建议…...

基于YOLOV5+Flask安全帽RTSP视频流实时目标检测

1、背景 在现代工业和建筑行业中&#xff0c;安全始终是首要考虑的因素之一。特别是在施工现场&#xff0c;工人佩戴安全帽是确保人身安全的基本要求。然而&#xff0c;人工监督难免会有疏漏&#xff0c;尤其是在大型工地或复杂环境中&#xff0c;确保每个人都佩戴安全帽变得非…...

Windows内置的服务器IIS(Internet Information Services)托管网站

一. 安装IIS 打开控制面板&#xff1a;在开始菜单搜索“控制面板”并打开它。程序和功能&#xff1a;点击“程序”然后选择“程序和功能”。启用或关闭Windows功能&#xff1a;在左侧菜单中选择“启用或关闭Windows功能”。查找并勾选IIS&#xff1a;在弹出的窗口中&#xff0c…...

虚幻引擎结构之UObject

一. UObject 的介绍 UObject 是虚幻引擎中的核心基础类,所有其他游戏对象和资源类都直接或间接地继承自它。作为虚幻引擎的基石,UObject 提供了多项关键功能,包括内存管理、序列化、反射(introspection)、垃圾回收以及元数据支持。在虚幻引擎中,UObject 类的实例通常被称…...

js的Reflect对象

Reflect 对象是 JavaScript ES6 中引入的一个内建对象&#xff0c;它提供了一系列与对象操作相关的方法。这些方法与 Object 对象上的方法类似&#xff0c;但在行为上有一些差异&#xff0c;并且更加规范和统一。Reflect 对象并不是一个构造函数&#xff0c;不能被 new 操作符调…...

this指向了谁?

看函数在执行的时候是如何调用的&#xff0c; 1 如果这个函数是用普通函数调用模式来进行调用&#xff0c;它内部的this指向了window; 2 如果一个函数在调用的时候是通过对象方法模式来进行调用&#xff0c;则它内部的this就是我们的对象; 3 如果一个函数在调用的时候通过构…...

基于Resnet、LSTM、Shufflenet及CNN网络的Daily_and_Sports_Activities数据集仿真

在深度学习领域&#xff0c;不同的网络结构设计用于解决特定的问题。本文将详细分析四种主流网络结构&#xff1a;卷积神经网络&#xff08;CNN&#xff09;、残差网络&#xff08;ResNet&#xff09;、长短期记忆网络&#xff08;LSTM&#xff09;和洗牌网络&#xff08;Shuff…...

mac系统vsCode中使用Better Comments在.vue文件里失效

问题&#xff1a;关于Better Comments默认在html、TS、JS中有效&#xff0c;在vue中无效,需要单独进行配置 windows系统可以参考友链Better Comments&#xff08;注释高亮&#xff09;在vue文件里失效的问题 关于Better Comments电脑的配置路径&#xff1a; Windows系统&…...

UE5.3 C++ Ceiusm中的POI 制作3DUI 结合坐标转化

一.核心思路WidgetComponent CesiumGloberAnchor 二.先制作POI 创建C Actor来制作&#xff0c;APOI。直接上代码 #pragma once#include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "CesiumGlobeAnchorComponent.h" #includ…...

一起学Git【第六节:查看版本差异】

git diff是 Git 版本控制系统中用于展示差异的强大工具。他可以用于查看文件在工作区、暂存区和版本库之间的差异、任意两个指定版本之间的差异和两个分支之间的差异等,接下来进行详细的介绍。 1.显示工作区与暂存区之间的差异 # 显示工作区和暂存区之间的差异,后面不加参数…...

numpy np.newaxis介绍

np.newaxis 是 NumPy 中用于增加数组维度的关键字。它的作用是为数组插入一个新的维度&#xff0c;从而改变数组的形状&#xff08;shape&#xff09;。 基本用法 np.newaxis 等价于 None&#xff0c;可以作为索引使用&#xff0c;用于在指定位置增加一个维度。增加的维度的大…...

小程序配置文件 —— 16 项目配置文件和配置 sass

目录 项目配置文件配置 sass 项目配置文件 在创建项目的时候&#xff0c;每个项目的根目录生成两个 config.json 文件&#xff08;project.config.json 和 project.private.config.json &#xff09;&#xff0c;用于保存开发者在工具上做的个性化配置&#xff0c;例如和编译有…...

【yolov5】实现FPS游戏人物检测,并定位到矩形框上中部分,实现自瞄

介绍 本人机器学习小白&#xff0c;通过语言大模型百度进行搜索&#xff0c;磕磕绊绊的实现了初步效果&#xff0c;能有一些锁头效果&#xff0c;但识别速度不是非常快&#xff0c;且没有做敌友区分&#xff0c;效果不是非常的理想&#xff0c;但在4399小游戏中爽一下还是可以…...

概率统计与随机过程--作业5

一、推导题 二、计算题 1、某单位为了研究太阳镜销售和广告费用之间的关系&#xff0c;搜集了以下数据&#xff0c;使用回归分析方法得到线性回归模型&#xff1a; 广告费用&#xff08;万元&#xff09;x 2 5 6 7 22 25 28 30 22 18 销售量&#xff08;个&#xf…...

“802.11g”,“802.11n”,“802.11ac”,“802.11ax”

802.11g、802.11n、802.11ac、802.11ax都是IEEE制定的无线局域网&#xff08;WLAN&#xff09;标准&#xff0c;它们各自具有不同的特点和性能。以下是对这四个标准的详细介绍&#xff1a; 1. 802.11g 定义&#xff1a;802.11g是IEEE制定的一种无线局域网标准&#xff0c;它提…...

Kubernetes 常用的网络插件

上篇内容跟大家简单聊了k8s网络模型原理。分别围绕着容器、Pod、Service、网络策略等展开了详细的讲解。这次想跟大家聊聊k8s的CNI网络插件。 CNI 是 Kubernetes 网络模型的核心组件&#xff0c;它是一个插件接口&#xff0c;允许用户选择和配置网络插件来管理 Pod 的网络。CN…...

Retrofit和rxjava 实现窜行请求,并行请求,循环多次请求,递归请求,错误重试

在使用 Retrofit 和 RxJava 时&#xff0c;可以通过多种方式实现多次请求&#xff0c;比如串行请求、并行请求、依赖请求等。以下是一些常见的实现方式&#xff1a; 1. 串行请求&#xff08;依赖关系&#xff09; 一个请求的结果作为另一个请求的输入&#xff0c;可以用 flat…...

2025年度好用便签推荐,电脑桌面便签app分享

在快节奏的现代生活中&#xff0c;高效的时间管理和任务规划变得尤为重要。一款好用的便签软件不仅能帮助我们记录灵感、待办事项&#xff0c;还能极大地提升我们的工作效率。 在众多电脑桌面便签中&#xff0c;好用便签以其出色的桌面便签功能脱颖而出&#xff0c;备受用户青…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

JavaScript 中的 ES|QL:利用 Apache Arrow 工具

作者&#xff1a;来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗&#xff1f;了解下一期 Elasticsearch Engineer 培训的时间吧&#xff01; Elasticsearch 拥有众多新功能&#xff0c;助你为自己…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

【HTML-16】深入理解HTML中的块元素与行内元素

HTML元素根据其显示特性可以分为两大类&#xff1a;块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

智能AI电话机器人系统的识别能力现状与发展水平

一、引言 随着人工智能技术的飞速发展&#xff0c;AI电话机器人系统已经从简单的自动应答工具演变为具备复杂交互能力的智能助手。这类系统结合了语音识别、自然语言处理、情感计算和机器学习等多项前沿技术&#xff0c;在客户服务、营销推广、信息查询等领域发挥着越来越重要…...