-
-
Save AdiRidA/5529e2114b91526b0dae8fc8a333380b to your computer and use it in GitHub Desktop.
RPG Crafting System Source Code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using RPG.Inventories; | |
namespace RPG.Crafting | |
{ | |
public class Craft : MonoBehaviour | |
{ | |
public void CraftItem(Inventory inventory, InventoryItem inventoryItem, CraftingRecipe.Recipes recipe) | |
{ | |
// Check if the player has the ingredients in the inventory. | |
if(HasIngredients(inventory, recipe)) | |
{ | |
// If true | |
// Rremove the items from the inventory. | |
RemoveItems(inventory, recipe); | |
// Add the recipe result item to the first empty slot in the inventory. | |
inventory.AddToFirstEmptySlot(inventoryItem, 1); | |
} | |
} | |
private void RemoveItems(Inventory inventory, CraftingRecipe.Recipes recipe) | |
{ | |
// Iterate through all of the ingredients in the specified recipe in the parameter. | |
foreach (CraftingRecipe.Ingredients ingredient in recipe.ingredients) | |
{ | |
// Check if the current ingredient iteration's item is stackable. | |
if (ingredient.item.IsStackable()) | |
{ | |
// If the item is stackable, get the slot index number the item is found in. | |
// Assign the slot index number in a variable. | |
int itemSlot = inventory.GetItemSlot(ingredient.item, ingredient.number); | |
// Remove the items from the player's inventory slot with the amount number. | |
inventory.RemoveFromSlot(itemSlot, ingredient.number); | |
} | |
else | |
{ | |
// If the item is NOT stackable, loop through the current foreach loop iteration's ingredient amount number. | |
for (int i = 0; i < ingredient.number; i++) | |
{ | |
// Get the slot index number that the item is found in. | |
// Because we know that the item is not stackable, we can simply say that the amount is 1. | |
int itemSlot = inventory.GetItemSlot(ingredient.item, 1); | |
// Remove the items from the player's inventory slot. | |
inventory.RemoveFromSlot(itemSlot, 1); | |
} | |
} | |
} | |
} | |
private bool HasIngredients(Inventory inventory, CraftingRecipe.Recipes recipe) | |
{ | |
// Create boolean to store result. | |
bool hasItem = false; | |
// Iterate through all of the ingredients in the specified recipe in the parameter. | |
foreach(CraftingRecipe.Ingredients ingredient in recipe.ingredients) | |
{ | |
// Check if the current ingredient iteration's item is stackable. | |
if(ingredient.item.IsStackable()) | |
{ | |
// If the item is stackable, get the inventory slot index number that the stack is in. | |
// We check if the returned value equals to or is greater than 0, because GetItemSlot returns -1 by default if no slot is found. | |
// Assign the if statement value to the boolean variable. | |
hasItem = inventory.GetItemSlot(ingredient.item, ingredient.number) >= 0; | |
} | |
else | |
{ | |
// If the item is NOT Stackable, check if the required item is in the player's inventory. | |
// Assign the if statement value to the boolean variable. | |
hasItem = inventory.HasItem(ingredient.item, ingredient.number); | |
} | |
// If the assigned value is false, the method will return false. | |
if(!hasItem) return false; | |
} | |
// The method will return true by default. | |
return true; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using RPG.Inventories; | |
namespace RPG.Crafting | |
{ | |
[CreateAssetMenu(menuName = "Crafting/Crafting Recipe")] | |
public class CraftingRecipe : ScriptableObject | |
{ | |
[SerializeField] Recipes[] recipes; | |
[System.Serializable] | |
public class Recipes | |
{ | |
public InventoryItem item; | |
public Ingredients[] ingredients; | |
} | |
[System.Serializable] | |
public class Ingredients | |
{ | |
public InventoryItem item; | |
public int number; | |
} | |
public Recipes[] GetCraftingRecipes() | |
{ | |
return recipes; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using RPG.UI.Inventories; | |
using RPG.Inventories; | |
namespace RPG.UI.Crafting | |
{ | |
public class CraftingSlotUI : MonoBehaviour, IItemHolder | |
{ | |
[SerializeField] InventoryItemIcon icon = null; | |
InventoryItem item; | |
public void Setup(InventoryItem item, int number) | |
{ | |
// Store the item parameter value in the local item variable. | |
this.item = item; | |
// Set both the item image and the amount number on the UI. | |
icon.SetItem(item, number); | |
} | |
public InventoryItem GetItem() | |
{ | |
// Return the set value in the item variable for the tooltip system | |
return item; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using UnityEngine.UI; | |
using RPG.Crafting; | |
using RPG.Inventories; | |
namespace RPG.UI.Crafting | |
{ | |
public class CraftingUI : MonoBehaviour | |
{ | |
[SerializeField] GameObject recipePrefab = null; | |
[SerializeField] CraftingSlotUI itemSlot = null; | |
[SerializeField] GameObject recipeArrow = null; | |
[SerializeField] Button craftButton = null; | |
CraftingRecipe craftingRecipe; | |
Inventory inventory; | |
private void Awake() | |
{ | |
//Get the player inventory component using the GetPlayerInventory method in the Inventory class. | |
inventory = Inventory.GetPlayerInventory(); | |
} | |
public void SetupRecipes(CraftingRecipe recipe) | |
{ | |
// Assign the parameter value (recipe) to the cached reference recipe (craftingRecipe). | |
craftingRecipe = recipe; | |
// Call the Redraw method which instantiates and sets up the UI elements. | |
Redraw(); | |
} | |
private void Redraw() | |
{ | |
// Destroy all of the child elements in the current gameobject's transform. | |
DestroyChild(transform); | |
// Iterate through all of the crafting recipes. | |
for (int i = 0; i < craftingRecipe.GetCraftingRecipes().Length; i++) | |
{ | |
// For each crafting recipe: | |
// Create a recipe holder gameobject in under the current transform. | |
var recipeHolder = Instantiate(recipePrefab, transform); | |
// Destroy all of the child elements in the recipe holder gameobject. | |
DestroyChild(recipeHolder.transform); | |
// Assign the current recipe iteration to a new variable. | |
var recipe = craftingRecipe.GetCraftingRecipes()[i]; | |
// Create and setup recipe ingredient gameobject elements under the recipe holder gameobject transform. | |
CreateRecipeIngredients(recipe, recipeHolder.transform); | |
// Create and setup recipe objects. Arrow image, recipe result item and craft button. | |
CreateRecipeObjects(craftingRecipe.GetCraftingRecipes()[i].item, recipeHolder.transform, recipe); | |
} | |
} | |
private void CreateRecipeIngredients(CraftingRecipe.Recipes recipe, Transform recipeHolder) | |
{ | |
// Store recipe ingredients length in a variable. | |
int ingredientsSize = recipe.ingredients.Length; | |
// Loop through all of the ingredients in the recipe. | |
for (int ingredient = 0; ingredient < ingredientsSize; ingredient++) | |
{ | |
// Create the itemSlot prefab and make it a child under the recipeHolder transform. | |
var ingredientItem = Instantiate(itemSlot, recipeHolder); | |
// Set up the item’s (ingredientItem) icon and number amount. | |
ingredientItem.Setup(recipe.ingredients[ingredient].item, recipe.ingredients[ingredient].number); | |
} | |
} | |
private void CreateRecipeObjects(InventoryItem inventoryItem, Transform recipeHolder, CraftingRecipe.Recipes recipe) | |
{ | |
// Create the arrow image UI element and make it a child under the recipeHolder transform. | |
var arrow = Instantiate(recipeArrow, recipeHolder); | |
// Instantiate the itemSlot prefab and make it a child under the recipeHolder transform. | |
var item = Instantiate(itemSlot, recipeHolder); | |
// Set up the item’s (item) icon and number amount. | |
item.Setup(inventoryItem, 1); | |
// Create the crafting button UI element and make it a child under the recipeHolder transform. | |
var button = Instantiate(craftButton, recipeHolder); | |
// Get the Craft script component from the button gameobject and store it in a variable. | |
var craft = button.GetComponent<Craft>(); | |
// Add a listener to the button onClick event using a lambda expression. | |
button.onClick.AddListener(() => craft.CraftItem(inventory, inventoryItem, recipe)); | |
} | |
private void DestroyChild(Transform transform) | |
{ | |
// Iterate through all child transforms of the parameter specified transform. | |
foreach (Transform child in transform) | |
{ | |
// Remove each iterated transform. | |
Destroy(child.gameObject); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using UnityEngine; | |
using RPG.Crafting; | |
using RPG.Controls; | |
using RPG.Movement; | |
namespace RPG.UI.Crafting | |
{ | |
public class ShowCraftingUI : MonoBehaviour, IRaycastable | |
{ | |
[SerializeField] CraftingRecipe craftingRecipe = null; | |
[SerializeField] CraftingUI craftingItems = null; | |
[SerializeField] GameObject craftingUI = null; | |
[SerializeField] float minimumCraftingDistance = 2.5f; | |
PlayerController playerController; | |
CharacterMovement characterMovement; | |
GameObject[] craftingTables; | |
private void Awake() | |
{ | |
// Find the player gameobject using the tag "Player", and get its PlayerController component. | |
playerController = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>(); | |
// Find the CharacterMovement component from the playerController. | |
characterMovement = playerController.GetComponent<CharacterMovement>(); | |
// Find all game objects with the tag "CraftingTable". | |
craftingTables = GameObject.FindGameObjectsWithTag("CraftingTable"); | |
} | |
private void Start() | |
{ | |
// Disable the crafting UI gameobject. | |
craftingUI.SetActive(false); | |
} | |
private bool IsWithinDistance(PlayerController playerController) | |
{ | |
// Iterate through the craftingTables GameObjects array. | |
foreach(GameObject craftingTable in craftingTables) | |
{ | |
// Using Vector3.Distance check the distance between the player and the current iteration. | |
// We use the cached PlayerController component to get the position of the gameobject. | |
// Return true if yes. | |
if(Vector3.Distance(playerController.transform.position, craftingTable.transform.position) < craftingRange) return true; | |
} | |
// Return false by default. | |
return false; | |
} | |
private void Update() | |
{ | |
// Check if IsWithinDistance returns false. | |
if(!IsWithinDistance(playerController) && craftingUI.activeSelf) | |
{ | |
// Disable the crafting UI gameobject. | |
craftingUI.SetActive(false); | |
} | |
} | |
public CursorType GetCursorType() | |
{ | |
// Return the desired CursorType enum member. | |
return CursorType.Crafting; | |
} | |
public bool HandleRaycast(PlayerController callingController) | |
{ | |
// Check if the player clicked the left mouse button. | |
if(Input.GetMouseButtonDown(0)) | |
{ | |
// If the left mouse button was clicked, check if the player is not within the minimum distance to the crafting table. | |
if(!IsWithinDistance(callingController)) | |
{ | |
// If outside minimum distance: | |
// Move player character to the crafting table position. | |
characterMovement.MoveTo(transform.position, 1f); | |
} | |
else | |
{ | |
// If within minimum distance: | |
// Cancel character movement using the navmesh isStopped property. | |
characterMovement.Cancel(); | |
// Setup the recipes in the crafting UI. | |
// The SetupRecipes function simply assigns craftingRecipe to the local variable in CraftingUI component (craftingItems). | |
// We don’t do this in Awake or Start for example, because there might be more than one crafting tables that offer different recipes. | |
craftingItems.SetupRecipes(craftingRecipe); | |
// Enable the crafting UI gameobject. | |
craftingUI.SetActive(!craftingUI.activeSelf); | |
} | |
} | |
return true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment