So in this game when the player picks up items from the scene I'm trying to have it draw the item in their inventory. The problem is whenever the player picks up an item the sprite is drawn in the wrong area. I'm calling additem from itemid class and sending it to the inventory class. when it is sent the id goes with it and that's how it knows which item to draw. I'm trying to draw it in the next empty slot in the inventory. in the inventory class if I comment in those AddItem(0) (or any number that has an item with it) it draws the sprite in the right location. any ideas on why it is drawing the sprite in the wrong location when it is called from the itemid class
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Inventory : MonoBehaviour {
ItemDataBase database;
GameObject inventoryPanel;
GameObject slotPanel;
public GameObject inventorySlot;
public GameObject inventoryItem;
int slotAmount;
public List<Item> items = new List<Item>();
public List<GameObject> slots = new List<GameObject>();
void Start()
{
database = GetComponent<ItemDataBase>();
slotAmount = 20;
inventoryPanel = GameObject.Find("Inventory Panel");
slotPanel = inventoryPanel.transform.FindChild("Slot Panel").gameObject;
for (int i = 0; i < slotAmount; i++)
{
items.Add(new Item());
// and empty slot
slots.Add(Instantiate(inventorySlot));
slots[i].GetComponent<Slot>().id = i;
//set parent to slot panel
slots[i].transform.SetParent(slotPanel.transform);
}
// AddItem(0);
// AddItem(1);
// AddItem(1);
// AddItem(1);
// Debug.Log(items[1].Title);
inventoryPanel.SetActive(false);
}
void Update()
{
if (Input.GetKeyDown("i") && inventoryPanel.activeSelf == false)
{
inventoryPanel.SetActive(true);
}
else if(Input.GetKeyDown("i") && inventoryPanel.activeSelf == true)
{
inventoryPanel.SetActive(false);
}
}
public void AddItem(int id)
{
inventoryPanel.SetActive(true);
Item itemToAdd = database.FetchItemByID(id);
if (itemToAdd.Stackable && checkIfItemIsInInventory(itemToAdd))
{
for (int i = 0; i < items.Count; i++)
{
if (items[i].ID == id)
{
ItemData data = slots[i].transform.GetChild(0).GetComponent<ItemData>();
data.amount++;
data.transform.GetChild(0).GetComponent<Text>().text = data.amount.ToString();
break;
}
}
}
else
{
for (int i = 0; i < items.Count; i++)
{
// in video had this set to -1
if (items[i].ID == -1)
{
items[i] = itemToAdd;
GameObject itemObj = Instantiate(inventoryItem);
itemObj.GetComponent<ItemData>().item=itemToAdd;
itemObj.GetComponent<ItemData>().amount = 1;
itemObj.GetComponent<ItemData>().slot = i;
itemObj.transform.SetParent(slots[i].transform);
itemObj.transform.position = Vector2.zero;
itemObj.GetComponent<Image>().sprite = itemToAdd.Sprite;
itemObj.name = itemToAdd.Title;
itemObj.name = itemToAdd.Title;
break;
}
}
}
}
bool checkIfItemIsInInventory(Item item)
{
for (int i = 0; i<items.Count; i++)
{
if (items[i].ID == item.ID)
{
return true;
}
}
return false;
}
void RemoveItem (int id)
{
for (int i = 0; i < items.Count; i++)
{
if (items[i].ID == id)
{
items[i] = new Item();
break;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemId : MonoBehaviour {
public int id;
public Inventory additem;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter2D (Collider2D other)
{
if (other.gameObject.tag == "Player")
{
Debug.Log(id);
additem.AddItem(1);
Destroy(gameObject);
}
}
}
Related
I'm really just a beginner and trying to learn game development, but i can't seem to figure out the logic behind this.. if the inventory has already an item inside and if the current object can't be stacked on top of it, then swap out the 2 object
the script i'm trying to implement it:
public void OnDrop(PointerEventData eventData)
{
//on drop if the inventory slot doesn't have child object then we know it's a free slot, so we can drag there the grabbed item.
if(transform.childCount == 0)
{
GameObject dropped = eventData.pointerDrag;
InventoryItem inventoryItem = dropped.GetComponent<InventoryItem>();
inventoryItem.parentAfterDrag = transform;
}
else
{
//on drop if the inventory has already an item inside and if the current object can't be stacked on top of it, then swap out the 2 object
//but how do i know what is the object that is inside this slot?
}
}
}
here is the InventoryManager script:
public class InventoryManager : MonoBehaviour
{
public int maxStackedItems = 4;
int selectedSlot = -1;
public InventorySlot[] inventorySlots;
public GameObject inventoryItemPrefab;
public GameObject mainInventory;
public bool isMainInventoryOpened;
public bool AddItem(Item item)
{
//checks if there is any slot with the same kind of item as this, which isnt in max stack
for (int i = 0; i < inventorySlots.Length; i++)
{
InventorySlot slot = inventorySlots[i];
InventoryItem itemInSlot = slot.GetComponentInChildren<InventoryItem>();
if (itemInSlot != null && itemInSlot.item == item && itemInSlot.count < maxStackedItems && itemInSlot.item.stackable == true)
{
itemInSlot.count++;
itemInSlot.RefreshCount();
return true;
}
}
//looks for an empty slot
for (int i = 0; i < inventorySlots.Length; i++)
{
InventorySlot slot = inventorySlots[i];
InventoryItem itemInSlot = slot.GetComponentInChildren<InventoryItem>();
if(itemInSlot == null)
{
SpawnNewItem(item, slot);
return true;
}
}
return false;
}
void SpawnNewItem(Item item, InventorySlot slot)
{
GameObject newItemGo = Instantiate(inventoryItemPrefab, slot.transform);
InventoryItem inventoryItem = newItemGo.GetComponent<InventoryItem>();
inventoryItem.InitializeItem(item);
}
public Item GetSelectedItem(bool use)
{
InventorySlot slot = inventorySlots[selectedSlot];
InventoryItem itemInSlot = slot.GetComponentInChildren<InventoryItem>();
if (itemInSlot != null)
{
Item item = itemInSlot.item;
if(use == true)
{
itemInSlot.count--;
if(itemInSlot.count <= 0)
{
Destroy(itemInSlot.gameObject);
}
else
{
itemInSlot.RefreshCount();
}
}
return item;
}
return null;
}
}
and the InventoryItem script:
public class InventoryItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
[HideInInspector] public Transform parentAfterDrag;
[HideInInspector] public Item item;
[HideInInspector] public int count = 1;
public Image image;
public TMP_Text countText;
public void InitializeItem (Item newItem)
{
item = newItem;
image.sprite = newItem.image;
RefreshCount();
}
public void RefreshCount()
{
countText.text = count.ToString();
bool textActive = count > 1;
countText.gameObject.SetActive(textActive);
}
public void OnBeginDrag(PointerEventData eventData)
{
parentAfterDrag = transform.parent;
transform.SetParent(transform.root);
transform.SetAsLastSibling();
image.raycastTarget = false;
}
public void OnDrag(PointerEventData eventData)
{
transform.position = Input.mousePosition;
}
public void OnEndDrag(PointerEventData eventData)
{
transform.SetParent(parentAfterDrag);
image.raycastTarget = true;
}
}
i've tried to figure out what is the item on that occupied slot but i don't seem to understand this logic yet.
I'm making simple 2d game. This is opening scene. (Logos images showing).I want to if mouse click down (0) Time passes and other image show. How can i do it ?
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class OpeningCanvasScript : MonoBehaviour
{
void Start()
{
StartCoroutine(otherImage());
}
private void Deactivate()
{
for (int i = 0; i < transform.childCount; i++)
{
transform.GetChild(i).gameObject.SetActive(false);
}
}
private IEnumerator otherImage()
{
for (int i = 0; i < transform.childCount; i++)
{
Deactivate();
transform.GetChild(i).gameObject.SetActive(true);
yield return new WaitForSeconds(3f);
// I want to if mouse click down (0) Time passes and other image show
}
SceneManager.LoadScene(2);
}
}```
I think i did it this way
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class OpeningCanvasScript : MonoBehaviour
{
bool finished = false;
void Start()
{
StartCoroutine(otherImage());
}
private void Deactivate()
{
for (int i = 0; i < transform.childCount; i++)
{
transform.GetChild(i).gameObject.SetActive(false);
}
}
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
finished = true;
}
}
private IEnumerator otherImage()
{
for (int i = 0; i < transform.childCount; i++)
{
finished = false;
Deactivate();
transform.GetChild(i).gameObject.SetActive(true);
StartCoroutine(waitSeconds());
yield return new WaitUntil(()=>finished);
}
SceneManager.LoadScene(2);
}
private IEnumerator waitSeconds()
{
yield return new WaitForSeconds(3f);
finished = true;
}
}
using UnityEngine;
using UnityEngine.UI;
public class HealthBarController : MonoBehaviour
{
private GameObject[] heartContainers;
private Image[] heartFills;
public Transform heartsParent;
public GameObject heartContainerPrefab;
private void Start()
{
// Should I use lists? Maybe :)
heartContainers = new GameObject[(int)PlayerStats.Instance.MaxTotalHealth];
heartFills = new Image[(int)PlayerStats.Instance.MaxTotalHealth];
PlayerStats.Instance.onHealthChangedCallback += UpdateHeartsHUD;
InstantiateHeartContainers();
UpdateHeartsHUD();
}
public void UpdateHeartsHUD()
{
SetHeartContainers();
SetFilledHearts();
}
void SetHeartContainers()
{
for (int i = 0; i < heartContainers.Length; i++)
{
if (i < PlayerStats.Instance.MaxHealth)
{
heartContainers[i].SetActive(true);
}
else
{
heartContainers[i].SetActive(false);
}
}
}
void SetFilledHearts()
{
for (int i = 0; i < heartFills.Length; i++)
{
if (i < PlayerStats.Instance.Health)
{
heartFills[i].fillAmount = 1;
}
else
{
heartFills[i].fillAmount = 0;
}
}
if (PlayerStats.Instance.Health % 1 != 0)
{
int lastPos = Mathf.FloorToInt(PlayerStats.Instance.Health);
heartFills[lastPos].fillAmount = PlayerStats.Instance.Health % 1;
}
}
void InstantiateHeartContainers()
{
for (int i = 0; i < PlayerStats.Instance.MaxTotalHealth; i++)
{
GameObject temp = Instantiate(heartContainerPrefab);
temp.transform.SetParent(heartsParent, false);
heartContainers[i] = temp;
heartFills[i] = temp.transform.Find("HeartFill").GetComponent<Image>();
}
}
}
This is the HealthbarController and it works when the damage is a button. Same with heal and addheart but I can't make my enemies do the damage.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DamageScript : MonoBehaviour
{
public void Hurt(float dmg)
{
PlayerStats.Instance.TakeDamage(dmg);
}
}
and this is the damage script for my enemies. How can I make enemy do damage to the player when colliding with the player? I tried with OnCollisionEnter but whenever I put it into the code I only got a bunch of errors.
What if you tried giving your enemy the tag "Enemy" and your player a sphere collider (isTrigger checked).
And then make a take damage script for example:
public class takeDamage : MonoBehaviour
{
private int PlayerHp = 10f;
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag( "Enemy")) {
PlayerHp -= 1;
Debug.Log("Hit, HP: " + PlayerHp);
//Add GUI update function here
}
}
}
and attach it to the player.
Don't forget to scale the sphere collider to the appropriate size.
so I have like 5 game object in my scene but I only scale each of them separately. However when I try to do that all of them start scaling simultaneously. Also, I have a placement indicator that would be used to instantiate the object on the plane. It seems that instead of the object itself, the placement indicator is the one that gets scaled. How should I fix that?
I have tried deactivating the placement indicator but did not work.
Here is the code for instantiating objects:
I limited the obj number to 5.
I use this script instead of the usual "PlaceonPlane" script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR.ARFoundation;
using UnityEngine.Experimental.XR;
using UnityEngine.UI;
using UnityEngine.XR.ARSubsystems;
public class ARTaptoPlaceObject : MonoBehaviour
{
private ARSessionOrigin arOrigin;
GameObject spawnedobj;
public GameObject placementIndicator;
private ARRaycastManager arRaycast;
public Pose placementPose;
public UIContoller sc;
public bool placementPoseIsValid = false;
private int count;
private string valu;
string prefabs;
void Start()
{
arOrigin = FindObjectOfType<ARSessionOrigin>();
arRaycast = FindObjectOfType<ARRaycastManager>();
count = 0;
}
// Update is called once per frame
void Update()
{
UpdatePlacementPose();
UpdatePlacementIndicator();
for (var i = 0; i < Input.touchCount; ++i)
{
if (Input.GetTouch(i).phase == TouchPhase.Began)
{
if (placementPoseIsValid && Input.GetTouch(i).tapCount == 2)
{
PlaceObject();
}
}
}
}
public void PlaceObject()
{
if (count <= 4)
{
if (sc.objectToPlace != null)
{
spawnedobj = Instantiate(sc.objectToPlace, placementPose.position, placementPose.rotation);
arOrigin.MakeContentAppearAt(spawnedobj.transform, spawnedobj.transform.position, spawnedobj.transform.rotation);
count++;
}
}
else
{
placementIndicator.SetActive(false);
}
}
private void UpdatePlacementIndicator()
{
if (placementPoseIsValid && count <= 4 && sc.active == false)
{
placementIndicator.SetActive(true);
placementIndicator.transform.SetPositionAndRotation(placementPose.position, placementPose.rotation);
}
else
{
placementIndicator.SetActive(false);
}
}
private void UpdatePlacementPose()
{
var screenCenter = Camera.current.ViewportToScreenPoint(new Vector3(0.5f, 0.5f));
var hits = new List<ARRaycastHit>();
arRaycast.Raycast(screenCenter, hits, UnityEngine.XR.ARSubsystems.TrackableType.Planes);
placementPoseIsValid = hits.Count > 0;
if (placementPoseIsValid)
{
placementPose = hits[0].pose;
var cameraForward = Camera.current.transform.forward;
var cameraBearing = new Vector3(cameraForward.x, 0, cameraForward.z).normalized;
placementPose.rotation = Quaternion.LookRotation(cameraBearing);
}
}
}
and here is the Scaler script that's attached to the button that would scale the object.
public class Scaler : MonoBehaviour
{
public UIContoller uc;
public ARTaptoPlaceObject ap;
private GameObject ReferenceToScale;
public void OnValueChange()
{
ReferenceToScale = (UnityEngine.GameObject)Resources.Load(uc.s_count, typeof(GameObject));
Vector3 t = ReferenceToScale.transform.localScale;
Vector3 scaleValue = t * 1.1f;
ReferenceToScale.transform.localScale = scaleValue;
}
Also the "objectToPlace" itself is in the "UI.Controller" script as I could not view it in the scene when it was in the "ARTaptoPlace" script
I'm trying to make a simple condition:
If the value I have, is less than the price it costs the item, the button is disabled.
If the value I have, is greater than or equal to the price it costs the item the button is enabled and I can buy it.
But when I test, I have some problems.
First, if I have less than the item cost the button is enabled, and only when I click on it it is when it disables.
Second, if I have less than the item cost and I click on it it disables, but if I get enough to purchase the item, the button is not enabled again.
How do I to be checked these variables all the time? If I have enough the button is enabled if you do not have it disables.
Bellow my scrip:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class BuySkin : MonoBehaviour {
public int price;
public Button buyBee1;
void OnEnable ()
{
//Register Button Events
buyBee1.onClick.AddListener (() => buySkin (buyBee1));
}
public void buySkin(Button button)
{
if (BeeCoinScore.coin >= price) {
BeeCoinScore.coin -= price;
buyBee1.interactable = false;
}
if (BeeCoinScore.coin < price) {
buyBee1.interactable = false;
}
}
void OnDisable ()
{
//Un-Register Button Events
buyBee1.onClick.RemoveAllListeners ();
}
}
Try this out with some prefabs!
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
public class GameController : MonoBehaviour
{
public int coins;
private int spherePrice = 100, cubePrice = 50;
public GameObject player;
public GameObject[] availablePrefabs;
public List<GameObject> mySkins;
public Button btnSphere, btnCube;
public Text txtSphere, txtCube;
void Start ()
{
string serializedMySkins = PlayerPrefs.GetString ("skins", "");
string serializedPlayer = PlayerPrefs.GetString ("player", "");
// skins desserialization
if (serializedMySkins == "")
mySkins = new List<GameObject> ();
else {
var a = serializedMySkins.Split (',');
for (int i = 0; i < a.Length; i++) {
if (a [i] == "Sphere") {
mySkins.Add (availablePrefabs [0]);
}
if (a [i] == "Cube") {
mySkins.Add (availablePrefabs [1]);
}
}
}
// player desserialization
if (serializedPlayer != "") {
if (serializedPlayer == "Sphere") {
player = availablePrefabs [0];
}
if (serializedPlayer == "Cube") {
player = availablePrefabs [1];
}
} else {
player = mySkins [0];
}
coins = PlayerPrefs.GetInt ("coins", 0);
coins = 1000;
}
void Update ()
{
if (mySkins.Contains (availablePrefabs [0])) {
txtSphere.text = "Usar esfera";
} else {
btnSphere.interactable = coins >= spherePrice;
}
if (mySkins.Contains (availablePrefabs [1])) {
txtCube.text = "Usar cubo";
} else {
btnCube.interactable = coins >= cubePrice;
}
}
public void play ()
{
player = (GameObject)Instantiate (player, new Vector2 (0, 0), Quaternion.identity);
}
public void verifySkin (GameObject skinPrefab)
{
if (mySkins.Contains (skinPrefab)) {
useSkin (skinPrefab);
} else if (coins >= priceOf (skinPrefab)) {
buySkin (skinPrefab, priceOf (skinPrefab));
}
}
public void buySkin (GameObject skinPrefab, int price)
{
mySkins.Add (skinPrefab);
coins -= price;
string skinsHash = "";
for (int i = 0; i < mySkins.Count; i++) {
skinsHash += mySkins [i].name + ",";
}
Debug.Log (skinsHash);
PlayerPrefs.SetInt ("coins", coins);
PlayerPrefs.SetString ("skins", skinsHash);
PlayerPrefs.Save ();
}
public void useSkin (GameObject skinPrefab)
{
player = skinPrefab;
PlayerPrefs.SetString ("player", player.name);
PlayerPrefs.Save ();
}
private int priceOf (GameObject skinPrefab)
{
if (skinPrefab == availablePrefabs [0])
return spherePrice;
else if (skinPrefab == availablePrefabs [1])
return cubePrice;
else
return 0;
}
}
OnEnable()is called when the object becomes enabled and active.
you need Update() as it is getting called every frame it will check whether your value is less than or greater than price of item.You may also try like this.
// I think that you are making an buymenu, so you can disable and enable your menu with ui button and check money you have
using System.Collections;
using UnityEngine.UI;
public class BuySkin : MonoBehaviour
{
public int price;
public static int money;// money you have
public Button thisbuyBee1;
public void buychkr()
{
if(price>= money)
{
thisbuyBee1.interactable = false;
}
else
{
thisbuyBee1.interactable = true;
}
}
void Update()
{
buychkr();
}
}