Originally did through the creation-delete object, but came across a project in the public domain, which does what I want, but in 2D. The project .

In general, as I understood the idea, we change the sprite on the table through a layer through ScriptableObject . enter image description here

enter image description here

ps What is OverlaySprite, an empty object? Why is he like a prefab, but gray, although he is active.

Main code:

CropAsset:

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; } 

Crop:

 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 } 

Tool:

 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 } 

TableTile:

 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; } } 

I want to do the same, but for 3D objects. I was recommended to change where Sprite and SpriteRenderer is used to Mesh and MeshRenderer.

My code is:

IngredientAsset:

 using System.Collections; using System.Collections.Generic; using UnityEngine; [CreateAssetMenu(fileName = "New Ingredient", menuName = "Ingredient")] public class IngredientAsset : ScriptableObject { public Mesh ingredientMesh; } 

enter image description here

Ingredient:

 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; } } 

EquipmentAsset:

 using System.Collections; using System.Collections.Generic; using UnityEngine; [CreateAssetMenu(fileName = "New Equipment", menuName = "Equipment")] public class EquipmentAsset : ScriptableObject { public Mesh equipmentMesh; } 

TableBox:

 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; } } 

But since the creation of my ScriptableObjects of the mesh type, in my version Crop swears at overlay.mesh .

enter image description here

The table itself:

enter image description here

Overlay: enter image description here Please help me figure out how to convert this function to 3D objects. Is it right that prompted me? Is it right to do so? It is also possible but with prefabs?

  • You will attach what you have already rewritten and where exactly the error appears. "My version of Crop swears at overlay.mesh" is not a description of the problem. - RiotBr3aker
  • OverlaySprite is, apparently, the object to draw, the logic is in the parent object. - RiotBr3aker
  • @ RiotBr3aker as I mentioned above, I didn’t really change anything except the mesh, mesh render. But I was advised so. Added information on your request, + screenshots. ps Why in the 2D project in the TableTile script, in the Crop field, an object of the CropAsset type is placed, and in my case (I kind of do the same). IngredientAsset does not lie in the Ingredient field (different types, but in the 2nd project it turns out). Perhaps something overlooked. - Artik Slayer

1 answer 1

First of all, it is worth ScriptableObject that ScriptableObject is some kind of container or, more correctly, a wrapper over some resources that can be instantiated and generally interact with it as an object.


Now this error:

enter image description here

The problem is that MeshRenderer does not store a mesh that draws , it receives it from MeshFilter . In 2D with sprites, exactly 1 object deals with this all, with meshes it is not.

Solving the problem is quite simple - you need to keep a link to the MeshFilter , to MeshRenderer we don’t care:

 public class TableBox : MonoBehaviour { public MeshFilter overlay; // ... 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) { // ... if (equipment != null) overlay.mesh = equipment.mesh; else if (ingredient != null) overlay.mesh = ingredient.GetIngrediendObject(); else overlay.mesh = null; } } 

Why in the 2D project in the TableTile script, in the Crop field, an object of the CropAsset type is placed, and in me (I kind of do the same). IngredientAsset does not lie in the Ingredient field (different types, but in the 2nd project it turns out).

I did not understand this at all, you have an ingredient field of type Ingredient , where you want to put an object of type IngredientAsset . That is why it does not work.

  • About the latter. => I'm talking about the same thing! See the very first screenshot of the 2D project. There in the field clearly visible place for an object of type CropAsset. Although in the code of the Table Tile script itself, an object of type Crop is indicated. Miracles? - Artik Slayer
  • There everything is correctly written: Crop Asset , your IngredientAsset fits into Ingredient , everything does not work, there are no miracles. - RiotBr3aker 7:16 pm
  • Perhaps due to the late hour I am scattered. But! I understand that I cannot put an Ingredient Asset object in Ingrediet, but the code from 2D can? Here is a screen . I apologize if my argument seems stupid to you. - Artik Slayer
  • The 2D code links ScriptableObject not to an object of type Crop , but in the field of an object of type 'Crop' - these are 2 different things. - RiotBr3aker 9:16 pm
  • Well thank you. And what if I want to do the same with the prefabs? Or is it better to create a separate question? - Artik Slayer