最初,我是通过创建和删除一个对象来完成的,但我遇到了一个公共领域的项目,它可以做我想做的事情,但是是 2D 的。项目。
一般来说,据我了解,这个想法是我们通过ScriptableObject通过图层更改桌子上的精灵
。
ps什么是OverlaySprite,一个空对象?为什么它像一个预制件,但是灰色的,虽然它是活动的。
主要代码:
作物资产:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Crop", menuName = "Crop")]
public class CropAsset : ScriptableObject
{
public Sprite seedSprite;
public Sprite deadSprite;
public Sprite doneSprite;
public bool seedIsOnGround = false;
}
庄稼:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Crop
{
public CropAsset asset;
public CropState state;
private float growthLevel;
private float waterLevel;
private bool isDead;
public bool Grow(float amount)
{
if (GetWaterState() == WaterState.Watered)
{
growthLevel += amount / 20f;
}
if (growthLevel >= 1f)
{
state = CropState.Done;
return true;
}
return false;
}
public WaterState Dry(float amount)
{
waterLevel -= amount / 8f;
return GetWaterState();
}
public WaterState GetWaterState ()
{
if (waterLevel > 0f)
{
return WaterState.Watered;
}
else if (waterLevel > -1f)
{
return WaterState.Dry;
}
else
{
state = CropState.Dead;
return WaterState.Dead;
}
}
public void Water ()
{
waterLevel = 1f;
}
public Crop (CropAsset a) {
asset = a;
state = CropState.Seed;
growthLevel = 0f;
waterLevel = 1f;
isDead = false;
}
public bool HasCrop()
{
if (asset == null)
return false;
else
return true;
}
public Sprite GetCropSprite()
{
if (asset == null)
return null;
switch (state)
{
case CropState.Seed:
return asset.seedSprite;
case CropState.Planted:
return asset.seedSprite;
case CropState.Dead:
return asset.deadSprite;
case CropState.Done:
return asset.doneSprite;
}
Debug.LogError("WHAT?!");
return asset.seedSprite;
}
public bool IsOnGround()
{
if (state == CropState.Planted && asset.seedIsOnGround)
return true;
else
return false;
}
public Sprite GetDoneSprite()
{
return asset.doneSprite;
}
public string GetName()
{
if (asset == null)
return null;
return asset.name;
}
}
public enum CropState
{
Seed,
Planted,
Dead,
Done
}
public enum WaterState
{
Watered,
Dry,
Dead
}
工具:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Tool", menuName = "Tool")]
public class Tool : ScriptableObject
{
public Sprite sprite;
public ToolType toolType;
}
public enum ToolType
{
Plow,
Watercan
}
平铺:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TableTile : MonoBehaviour
{
public SpriteRenderer overlay;
public Crop crop;
public Tool tool;
private void Start()
{
if (crop.HasCrop())
overlay.sprite = crop.GetCropSprite();
else if (tool != null)
overlay.sprite = tool.sprite;
}
public void Interact(Crop c, Tool t, PlayerInteraction player)
{
player.SetCrop(crop);
crop = c;
player.SetTool(tool);
tool = t;
if (tool != null)
overlay.sprite = tool.sprite;
else if (crop != null)
overlay.sprite = crop.GetCropSprite();
else
overlay.sprite = null;
}
}
我想做同样的事情,但对于 3D 对象。建议我将使用 Sprite 和 SpriteRenderer 的位置更改为 Mesh 和 MeshRenderer。
我的代码:
成分资产:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Ingredient", menuName = "Ingredient")]
public class IngredientAsset : ScriptableObject {
public Mesh ingredientMesh;
}
成分:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class Ingredient : MonoBehaviour {
public IngredientAsset asset;
public Ingredient (IngredientAsset a) {
asset = a;
}
public bool HasIngrediend()
{
if (asset == null)
return false;
else
return true;
}
public Mesh GetIngrediendObject()
{
if (asset == null)
return null;
return asset.ingredientMesh;
}
}
设备资产:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Equipment", menuName = "Equipment")]
public class EquipmentAsset : ScriptableObject {
public Mesh equipmentMesh;
}
表框:
using System.Collections.Generic;
using UnityEngine;
public class TableBox : MonoBehaviour {
public MeshRenderer overlay;
public Ingredient ingredient;
public EquipmentAsset equipment;
private void Start()
{
if (ingredient.HasIngrediend())
overlay.mesh = ingredient.GetIngrediendObject();
else if (equipment != null)
overlay.mesh = equipment.mesh;
}
public void Interact(Ingredient c, EquipmentAsset t, PlayerInteraction player)
{
player.SetIngredient(ingredient);
ingredient = c;
player.SetEquipment(equipment);
equipment = t;
if (equipment != null)
overlay.sprite = equipment.mesh;
else if (ingredient != null)
overlay.mesh = ingredient.GetIngrediendObject();
else
overlay.mesh = null;
}
}
Но начиная с момента создания моих ScriptableObjects типа mesh, в моей версии Crop ругается на overlay.mesh.
Сам стол:
Overlay:
Прошу помочь разобраться как преобразовать данную функцию к 3Д объектам. Правильно ли то что мне подсказали? Правильно ли так делать? Можно также но с префабами?




Для начала стоит пояснить, что
ScriptableObject- это некого рода контейнер или, вернее, обертка над какими-то ресурсами, который можно инстанциировать и вообще взаимодействовать с ним, как с объектом.Теперь эта ошибка:
Вся проблема в том, что
MeshRendererне хранит меш, который рисует, он получает ее отMeshFilter. В 2д со спрайтами этим всем занимается ровно 1 объект, с мешами это не так.解决这个问题很简单——你需要存储一个对 的引用
MeshFilter,MeshRenderer我们不关心它:我根本不明白,你的成分字段有一个类型
Ingredient,你想在其中放置一个类型的对象IngredientAsset。这就是为什么它不起作用。