Hello programmers all around the world. I have made myself an inventory system for my game. Only problem is that when I click on item and then drag it to and empty slot it doesn't move and I kinda don't see the error which I am having and I have tried to debug it but without success any help? Here is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class Inventory : MonoBehaviour {
private RectTransform inventoryRect;
private float inventoryWidth;
private float inventoryHeight;
public int slots;
public int rows;
public float slotPaddingLeft;
public float slotPaddingTop;
public float slotSize;
public GameObject slotPrefab;
private static Slot from;
private static Slot to;
private List<GameObject> allslots;
public GameObject iconPrefab;
private static GameObject hoverObject;
private static int emptySlots;
public Canvas canvas;
private float hoverYOffset;
private bool isPressed;
public EventSystem eventSystem;
public static int EmptySlots{
get{ return emptySlots;}
set{ emptySlots = value;}
}
// Use this for initialization
void Start () {
CreateLayout ();
canvas.enabled = false;
isPressed = false;
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown (KeyCode.I)) {
if (Input.GetKeyDown (KeyCode.I)) {
canvas.enabled = false;
}
canvas.enabled = true;
}
if (Input.GetMouseButtonUp (0)) {
if (!eventSystem.IsPointerOverGameObject (-1) && from != null) {
from.GetComponent<Image> ().color = Color.white;
from.ClearSlot ();
Destroy (GameObject.Find ("Hover"));
to = null;
from = null;
hoverObject = null;
}
}
if (hoverObject != null) {
Vector2 position;
RectTransformUtility.ScreenPointToLocalPointInRectangle (canvas.transform as RectTransform, Input.mousePosition, canvas.worldCamera, out position);
position.Set (position.x, position.y - hoverYOffset);
hoverObject.transform.position = canvas.transform.TransformPoint (position);
}
}
private void CreateLayout(){
allslots = new List<GameObject> ();
hoverYOffset = slotSize * 0.01f;
emptySlots = slots;
inventoryWidth = (slots / rows) * (slotSize + slotPaddingLeft) + slotPaddingLeft;
inventoryHeight = rows * (slotSize + slotPaddingTop) + slotPaddingTop;
inventoryRect = GetComponent<RectTransform> ();
inventoryRect.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, inventoryWidth);
inventoryRect.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, inventoryHeight);
int colums = slots / rows;
for (int y = 0; y < rows; y++) {
for (int x = 0; x < colums; x++) {
GameObject newSlot = (GameObject)Instantiate (slotPrefab);
RectTransform slotRect = newSlot.GetComponent<RectTransform> ();
newSlot.name = "Slot";
newSlot.transform.SetParent (this.transform.parent);
slotRect.localPosition = inventoryRect.localPosition + new Vector3 (slotPaddingLeft * (x + 1) + (slotSize * x), -slotPaddingTop * (y + 1) - (slotSize * y));
slotRect.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, slotSize);
slotRect.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, slotSize);
allslots.Add (newSlot);
}
}
}
public bool AddItem(Item item){
if (item.maxSize == 1) {
PlaceEmpty (item);
return true;
}
else {
foreach (GameObject slot in allslots) {
Slot temporary = slot.GetComponent<Slot> ();
if (!temporary.IsEmpty) {
if (temporary.CurrentItem.type == item.type && temporary.IsAvailable) {
temporary.AddItem (item);
return true;
}
}
}
if (emptySlots > 0) {
PlaceEmpty (item);
}
}
return false;
}
private bool PlaceEmpty(Item item){
if (emptySlots > 0) {
foreach (GameObject slot in allslots) {
Slot temporary = slot.GetComponent<Slot> ();
if (temporary.IsEmpty) {
temporary.AddItem (item);
emptySlots--;
return true;
}
}
}
return false;
}
public void MoveItem(GameObject clicked){
if (from == null) {
if (!clicked.GetComponent<Slot> ().IsEmpty) {
from = clicked.GetComponent<Slot> ();
from.GetComponent<Image> ().color = Color.gray;
hoverObject = (GameObject)Instantiate (iconPrefab);
hoverObject.GetComponent<Image> ().sprite = clicked.GetComponent<Image> ().sprite;
hoverObject.name = "Hover";
RectTransform hoverTransform = hoverObject.GetComponent<RectTransform> ();
RectTransform clickedTransform = clicked.GetComponent<RectTransform> ();
hoverTransform.SetSizeWithCurrentAnchors (RectTransform.Axis.Horizontal, clickedTransform.sizeDelta.x);
hoverTransform.SetSizeWithCurrentAnchors (RectTransform.Axis.Vertical, clickedTransform.sizeDelta.y);
hoverObject.transform.SetParent (GameObject.Find ("Canvas").transform, true);
hoverObject.transform.localScale = from.gameObject.transform.localScale;
}
}
else if (to = null) {
to = clicked.GetComponent<Slot> ();
Destroy (GameObject.Find ("Hover"));
}
if (to != null && from != null) {
Stack<Item> tmpTo = new Stack<Item> (to.Items);
to.AddItems (from.Items);
if (tmpTo.Count == 0) {
from.ClearSlot ();
}
else {
from.AddItems (tmpTo);
}
from.GetComponent<Image> ().color = Color.white;
to = null;
from = null;
hoverObject = null;
}
}
}
The method which is causing the problem is the MoveItem() sadly it is not a nullreference or nullpointer and I simply am out of ideas been strugling with it for a couple of days... Any advice on how to fix this would be helpfull and much welcomed indeed. Thanks in advance!
I haven't taken a long look at your code but right away I saw this issue:
else if (to = null) {
to = clicked.GetComponent<Slot> ();
Destroy (GameObject.Find ("Hover"));
}
This is causing the end location to be set to null. To fix this, change to double equals like so:
else if (to == null) {
to = clicked.GetComponent<Slot> ();
Destroy (GameObject.Find ("Hover"));
}
If this does not solve your problem, let me know and I'll look at your code harder.
Related
public class FootPaint : MonoBehaviour
{
#region --- helpers --
public enum enumFoot
{
Left,
Right,
}
#endregion
public GameObject LeftPrefab;
public GameObject RightPrefab;
public float FootprintSpacer = 1.0f;
private Vector3 LastFootprint;
private enumFoot WhichFoot;
public GameObject[] intdexPos;
private void Start()
{
LastFootprint = this.transform.position;
}
private void Update()
{
FootPaints();
}
public void FootPaints()
{
if (CheckPaintItem.instance.isPaint == true && gameObject.name == "PlayerSeek")
{
float DistanceSinceLastFootprint = Vector3.Distance(transform.position, LastFootprint);
if (DistanceSinceLastFootprint >= FootprintSpacer)
{
LastFootprint = this.transform.position;
if (WhichFoot == enumFoot.Left)
{
SpawnFootDecal(LeftPrefab);
WhichFoot = enumFoot.Right;
}
else if (WhichFoot == enumFoot.Right)
{
SpawnFootDecal(RightPrefab);
WhichFoot = enumFoot.Left;
}
LastFootprint = new Vector3(this.transform.position.x, this.transform.position.y + 1f, this.transform.position.z);
}
}
}
public void SpawnFootDecal(GameObject prefab)
{
int index = Random.Range(0, intdexPos.Length);
//where the ray hits the ground we will place a footprint
GameObject decal = Instantiate(prefab);
decal.transform.position = intdexPos[index].transform.position;
decal.transform.Rotate(Vector3.forward, intdexPos[index].transform.eulerAngles.y);
//turn the footprint to match the direction the player is facing
}
}
public class CheckPaintItem : MonoBehaviour
{
public static CheckPaintItem instance;
#region boolPaint
[HideInInspector]
public bool isPaint = false;
[HideInInspector]
public bool isPaintYellow = false;
[HideInInspector]
public bool isPaintRed = false;
[HideInInspector]
public bool isPaintBlue = false;
[HideInInspector]
public bool isPaintGreen = false;
#endregion
private float currentMoveSpeed;
private void Awake()
{
instance = this;
}
private void Start()
{
currentMoveSpeed = 2.5f;
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag == "PaintsYellow")
{
Debug.Log("Yellow");
isPaint = true;
isPaintYellow = true;
StartCoroutine(timePaint());
}
else if (other.gameObject.tag == "PaintsRed")
{
isPaint = true;
isPaintRed = true;
StartCoroutine(timePaint());
}
else if (other.gameObject.tag == "PaintsBlue")
{
isPaint = true;
isPaintBlue = true;
StartCoroutine(timePaint());
}
else if (other.gameObject.tag == "PaintsGreen")
{
isPaint = true;
isPaintGreen = true;
StartCoroutine(timePaint());
}
else
{
isPaint = false;
isPaintYellow = false;
isPaintRed = false;
isPaintBlue = false;
isPaintGreen = false;
}
if (other.gameObject.tag == "PaintsGlue")
{
StartCoroutine(changeMoveSpeedSlow());
}
if (other.gameObject.tag == "Speed")
{
StartCoroutine(changeMoveSpeedFast());
Destroy(other.gameObject);
}
}
IEnumerator changeMoveSpeedSlow()
{
PlayerController.instance._moveSpeed = PlayerController.instance._moveSpeed / 2 + 0.2f;
yield return new WaitForSeconds(5f);
PlayerController.instance._moveSpeed = currentMoveSpeed;
}
IEnumerator changeMoveSpeedFast()
{
PlayerController.instance._moveSpeed = PlayerController.instance._moveSpeed + 1f;
yield return new WaitForSeconds(5f);
PlayerController.instance._moveSpeed = currentMoveSpeed;
}
IEnumerator timePaint()
{
yield return new WaitForSeconds(15f);
isPaint = false;
}
}
I want to code the game "hide and seek", but I had a problem when the character stepped into a puddle of paint.
My game has 1 character finding and 5 moving AIs, I want whether the AI or the player steps into the puddle, it will leave footprints. But I have problem with above scripts tag, I add script tag with all characters.
So one character walks in, all the other characters show their footsteps. I don't know if my direction is correct. If anyone wants to understand more about the game I'm coding, you can go to youtube and type hide and seek and it will come out.
Thank you.
It seems to me, that the problem lies within CheckPaintItem.instance.isPaint. I don't know what that script is exactly, but it's probably a singleton pattern as there is an instance call. If that's the case, then you're checking if any CheckPaintItem is true globally as it's fields are pretty much static. So make changes to CheckPaintItem or show us what it does exactly.
I inherited by my ex collegue a Unity game. Now I need to implement this behaviour. The game consist in a car drive by user using Logitech steering.
Now I need to show a Text every X minute in a part of the screen like "What level of anxiety do you have ? " Ad the user should to set a value from 0 to 9 using the Logitech steering but I really don't know where to start.
This is my manager class:
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
namespace DrivingTest
{
// Braking test Manager
public class BtManager : BaseTestManger
{
// Public variables
public BreakCar breakCar;
public float minBrakeThreshold = 0.2f;
internal int vehicalSpeed;
internal int noOfEvents;
internal float durationOfTest;
// Private variables
private IRDSPlayerControls playerControlCar;
protected int xSpeed;
protected int ySpeed;
private float brakeEventStartTime;
private float brakeEventDifferenceTime;
private SafetyDistanceCheck safetyDistanceCheck;
protected float totalSafetyDistance;
protected int totalSafetyDistanceCount;
private List<float> averageEventReactionTime = new List<float>();
#region Init
// Use this for initialization
public override void Start()
{
base.Start();
playerControlCar = car.GetComponent<IRDSPlayerControls>();
safetyDistanceCheck = car.GetComponent<SafetyDistanceCheck>();
}
public override void OnEnable()
{
base.OnEnable();
BreakCar.BrakeStart += BrakeCarEvent;
BreakCar.BrakeEventEnd += CallTestOver;
}
public override void OnDisable()
{
base.OnDisable();
BreakCar.BrakeStart -= BrakeCarEvent;
BreakCar.BrakeEventEnd -= CallTestOver;
}
protected override void SetUpCar()
{
car.AddComponent<SelfDriving>();
}
#endregion
/// <summary>
/// Calls the main Test over method.
/// </summary>
private void CallTestOver()
{
GameManager.Instance.Testover();
}
protected override void OnSceneLoaded(eTESTS test)
{
UiManager.Instance.UpdateInstructions(Constants.BT_INSTRUCTION);
}
protected override void GetApiParams()
{
NextTestOutput nextTestOutput = GameManager.Instance.currentTest;
if (nextTestOutput.content != null && nextTestOutput.content.Count > 0)
{
foreach (var item in nextTestOutput.content[0].listInputParameter)
{
switch ((ePARAMETERS)item.id)
{
case ePARAMETERS.X_SPEED:
xSpeed = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.Y_SPEED:
ySpeed = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.SPEED_OF_VEHICLE:
vehicalSpeed = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.NUMBER_OF_EVENTS:
noOfEvents = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.DURATION_OF_TEST:
durationOfTest = float.Parse(item.Value) * 60; //converting minutes into seconds
break;
}
}
SetupBrakeCar();
}
}
protected virtual void SetupBrakeCar()
{
DOTween.Clear();
durationOfTest = noOfEvents * Random.Range(10,20); // The random value is the time between two consecutive tests.
breakCar.SetInitalParams(new BrakeCarInit
{
carMaxSpeed = vehicalSpeed * 0.95f,
durationOfTest = durationOfTest,
noOfEvents = noOfEvents,
xSpeed = xSpeed,
ySpeed = ySpeed
});
breakCar.distanceCheck = true;
}
protected override void SubmitRestultToServer()
{
SubmitTest submitTest = new SubmitTest
{
outputParameters = new List<SaveOutputParameter>
{
new SaveOutputParameter
{
id = (int)ePARAMETERS.OUT_REACTION_TIME,
value = ((int)(GetEventReactionTimeAvg () * Constants.FLOAT_TO_INT_MULTIPLAYER)).ToString()
},
new SaveOutputParameter
{
id = (int)ePARAMETERS.OUT_AVG_RT,
value = GetReactionResult().ToString()
}
}
};
WebService.Instance.SendRequest(Constants.API_URL_FIRST_SAVE_TEST_RESULT, JsonUtility.ToJson(submitTest), SubmitedResultCallback);
}
protected override void ShowResult()
{
UiManager.Instance.UpdateStats(
(
"1. " + Constants.EVENT_REACTION + (GetEventReactionTimeAvg() * Constants.FLOAT_TO_INT_MULTIPLAYER).ToString("0.00") + "\n" +
"2. " + Constants.REACTION_TIME + reactionTest.GetReactionTimeAvg().ToString("0.00")
));
}
public void LateUpdate()
{
//Debug.Log("TH " + .Car.ThrottleInput1 + " TH " + playerControlCar.Car.ThrottleInput + " brake " + playerControlCar.Car.Brake + " brake IP " + playerControlCar.Car.BrakeInput);
//Debug.Log("BrakeCarEvent "+ brakeEventStartTime + " Player car " + playerControlCar.ThrottleInput1 + " minBrakeThreshold " + minBrakeThreshold);
if (brakeEventStartTime > 0 && playerControlCar.Car.ThrottleInput1 > minBrakeThreshold)
{
brakeEventDifferenceTime = Time.time - brakeEventStartTime;
Debug.Log("Brake event diff " + brakeEventDifferenceTime);
Debug.Log("Throttle " + playerControlCar.Car.ThrottleInput1);
averageEventReactionTime.Add(brakeEventDifferenceTime);
brakeEventStartTime = 0;
safetyDistanceCheck.GetSafetyDistance(SafetyDistance);
}
}
private void SafetyDistance(float obj)
{
totalSafetyDistance += obj;
++totalSafetyDistanceCount;
}
/// <summary>
/// Records the time when the car ahead starts braking
/// </summary>
protected void BrakeCarEvent()
{
brakeEventStartTime = Time.time;
Debug.Log("BrakeCarEvent ");
}
/// <summary>
/// calculates the average time taken to react
/// </summary>
public float GetEventReactionTimeAvg()
{
float avg = 0;
foreach (var item in averageEventReactionTime)
{
avg += item;
}//noofevents
return avg / (float)averageEventReactionTime.Count;
}
}
}
EDIT
I create new class FearTest:
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace DrivingTest
{
public class FearTest : MonoBehaviour
{
//public GameObject redDot;
public TextMeshPro textAnsia2;
public TextMesh textAnsia3;
public int shouldEvaluateTest = 0; // 0 - false, 1 - true
public int secondsInterval;
public int secondsToDisaply;
public int radiusR1;
public int radiusR2;
public int reactionTestDuration;
public int maxDots;
public float dotRadius = 1;
private float endTime;
private float dotDisaplyAtTime;
private List<float> dotDisplayReactTime = new List<float>();
private int missedSignals;
private int currentDotsCount;
private bool isReactionAlreadyGiven;
public bool ShouldEvaluateTest
{
get
{
return shouldEvaluateTest != 0;
}
}
void OnEnable()
{
GameManager.TestSceneLoaded += OnSceneLoaded;
}
private void OnDisable()
{
GameManager.TestSceneLoaded -= OnSceneLoaded;
}
#region Scene Loaded
private void OnSceneLoaded(eTESTS test)
{
if (SceneManager.GetActiveScene().name != test.ToString())
return;
Reset();
GetApiParams();
}
#endregion
private void GetApiParams()
{
#if UNITY_EDITOR
if (!GameManager.Instance)
{
Init();
return;
}
#endif
Debug.Log("called rt");
NextTestOutput nextTestOutput = GameManager.Instance.currentTest;
if (nextTestOutput.content != null && nextTestOutput.content.Count > 0)
{
foreach (var item in nextTestOutput.content[0].listInputParameter)
{
switch ((ePARAMETERS)item.id)
{
case ePARAMETERS.RT_ENABLE:
shouldEvaluateTest = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RT_DURATION:
reactionTestDuration = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_FREQ:
secondsInterval = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_MAX_COUNT:
maxDots = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_RADIUS_R1:
radiusR1 = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_RADIUS_R2:
radiusR2 = System.Convert.ToInt32(item.Value);
break;
case ePARAMETERS.RED_DOT_SIZE:
dotRadius = float.Parse(item.Value)/10f;
break;
case ePARAMETERS.RED_DOT_TIME:
secondsToDisaply = System.Convert.ToInt32(item.Value);
break;
}
}
Debug.Log("called rt "+ shouldEvaluateTest);
/*if (ShouldEvaluateTest)
{
Init();
}*/
Init();//dopo bisogna sistemare il shoudl evaluatetest
}
}
Coroutine displayCoroutine;
public void Init()
{
endTime = Time.time + reactionTestDuration + 10;
SetRedDotSize();
displayCoroutine = StartCoroutine(RedDotDisplay());
}
private IEnumerator RedDotDisplay()
{
yield return new WaitForSeconds(2);
while (true)
{
SetRandomDotPosition();
RedDot(true);
isReactionAlreadyGiven = false;
dotDisaplyAtTime = Time.time;
currentDotsCount++;
yield return new WaitForSeconds(secondsToDisaply);
if(!isReactionAlreadyGiven)
{
missedSignals++;
}
RedDot(false);
if ((reactionTestDuration > 0 && endTime <= Time.time) || (maxDots > 0 && currentDotsCount >= maxDots))
break;
float waitTime = secondsInterval - secondsToDisaply;
yield return new WaitForSeconds(waitTime);
}
}
private void Update()
{
if (!ShouldEvaluateTest)
return;
if (!isReactionAlreadyGiven && /*redDot.activeSelf &&*/ (LogitechGSDK.LogiIsConnected(0) && LogitechGSDK.LogiButtonIsPressed(0, 23)))
{
isReactionAlreadyGiven = true;
float reactionTime = Time.time - dotDisaplyAtTime;
Debug.Log("Reaction Time RT : " + reactionTime);
RedDot(false);
dotDisplayReactTime.Add(reactionTime);
}
}
public double GetReactionTimeAvg()
{
double avg = 0;
foreach (var item in dotDisplayReactTime)
{
avg += item;
}
//avg / currentDotsCount
return avg / (float)dotDisplayReactTime.Count;
}
public double GetMissedSignals()
{
return ((float) missedSignals / (float) currentDotsCount) * 100;
}
private void RedDot(bool state)
{
//redDot.SetActive(state);
textAnsia2.SetText("Pippo 2");
}
private void SetRedDotSize()
{
//redDot.transform.localScale *= dotRadius;
textAnsia2.transform.localScale *= dotRadius;
textAnsia3.transform.localScale *= dotRadius;
}
private void SetRandomDotPosition()
{
//redDot.GetComponent<RectTransform>().anchoredPosition = GetRandomPointBetweenTwoCircles(radiusR1, radiusR2)*scale;
float scale = ((Screen.height*0.9f) / radiusR2) * 0.9f;
Vector3 pos = GetRandomPointBetweenTwoCircles(radiusR1, radiusR2) * scale;
Debug.Log("RT temp pos : " + pos);
pos = new Vector3(500, 500, 0);
Debug.Log("RT pos : " + pos);
// redDot.transform.position = pos;
Vector3 pos2 = new Vector3(20, 20, 0);
Debug.Log("text ansia 2 : " + pos2);
textAnsia2.transform.position = pos2;
textAnsia3.transform.position = pos;
}
#region Getting Red Dot b/w 2 cricles
/*
Code from : https://gist.github.com/Ashwinning/89fa09b3aa3de4fd72c946a874b77658
*/
/// <summary>
/// Returns a random point in the space between two concentric circles.
/// </summary>
/// <param name="minRadius"></param>
/// <param name="maxRadius"></param>
/// <returns></returns>
Vector3 GetRandomPointBetweenTwoCircles(float minRadius, float maxRadius)
{
//Get a point on a unit circle (radius = 1) by normalizing a random point inside unit circle.
Vector3 randomUnitPoint = Random.insideUnitCircle.normalized;
//Now get a random point between the corresponding points on both the circles
return GetRandomVector3Between(randomUnitPoint * minRadius, randomUnitPoint * maxRadius);
}
/// <summary>
/// Returns a random vector3 between min and max. (Inclusive)
/// </summary>
/// <returns>The <see cref="UnityEngine.Vector3"/>.</returns>
/// <param name="min">Minimum.</param>
/// <param name="max">Max.</param>
Vector3 GetRandomVector3Between(Vector3 min, Vector3 max)
{
return min + Random.Range(0, 1) * (max - min);
}
#endregion
#region Reset
private void Reset()
{
if (displayCoroutine != null)
StopCoroutine(displayCoroutine);
RedDot(false);
shouldEvaluateTest = 0;
reactionTestDuration = 0;
secondsInterval = 0;
missedSignals = 0;
maxDots = 0;
radiusR1 = 0;
radiusR2 = 0;
dotRadius = 1;
secondsToDisaply = 0;
endTime = 0;
dotDisaplyAtTime = 0;
dotDisplayReactTime.Clear();
//redDot.transform.localScale = Vector3.one;
textAnsia2.transform.localScale = Vector3.one;
textAnsia3.transform.localScale = Vector3.one;
currentDotsCount = 0;
isReactionAlreadyGiven = true;
}
#endregion
}
}
When "SetRandomDotPosition" method is called, in my scene I can display in a random position of the screen the RedDot (that is a simple image with a red dot), but I m not able to display my textAnsia2. How can I fixed it ?
I hope this will help you to get started :
https://vimeo.com/709527359
the scripts:
https://imgur.com/a/csNKwEh
I hope that in the video i covered every step that i've made.
Edit: The only thing is for you to do is to make the input of the Wheel to work on the slider. Try to make a simple script: when the text is enabled then the input from a joystick to work on that . When is disabled switch it back for his purpose .
I am currently messing around with a procedural 2D game in unity. Below are the scripts i am using to generate the dungeon and wanted to know if there was anyway of specifying a standard starting room. I have prefab room built but would like to have a single prefab room players always start in.
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class DungeonGeneration : MonoBehaviour {
[SerializeField]
private int numberOfRooms;
[SerializeField]
private int numberOfObstacles;
[SerializeField]
private Vector2Int[] possibleObstacleSizes;
[SerializeField]
private int numberOfEnemies;
[SerializeField]
private GameObject[] possibleEnemies;
[SerializeField]
private GameObject goalPrefab;
[SerializeField]
private TileBase obstacleTile;
private Room[,] rooms;
private Room currentRoom;
private static DungeonGeneration instance = null;
void Awake () {
if (instance == null) {
DontDestroyOnLoad (this.gameObject);
instance = this;
this.currentRoom = GenerateDungeon ();
} else {
string roomPrefabName = instance.currentRoom.PrefabName ();
GameObject roomObject = (GameObject) Instantiate (Resources.Load (roomPrefabName));
Tilemap tilemap = roomObject.GetComponentInChildren<Tilemap> ();
instance.currentRoom.AddPopulationToTilemap (tilemap, instance.obstacleTile);
Destroy (this.gameObject);
}
}
void Start () {
string roomPrefabName = this.currentRoom.PrefabName ();
GameObject roomObject = (GameObject) Instantiate (Resources.Load (roomPrefabName));
Tilemap tilemap = roomObject.GetComponentInChildren<Tilemap> ();
this.currentRoom.AddPopulationToTilemap (tilemap, this.obstacleTile);
}
private Room GenerateDungeon() {
int gridSize = 3 * numberOfRooms;
rooms = new Room[gridSize, gridSize];
Vector2Int initialRoomCoordinate = new Vector2Int ((gridSize / 2) - 1, (gridSize / 2) - 1);
Queue<Room> roomsToCreate = new Queue<Room> ();
roomsToCreate.Enqueue (new Room(initialRoomCoordinate.x, initialRoomCoordinate.y));
List<Room> createdRooms = new List<Room> ();
while (roomsToCreate.Count > 0 && createdRooms.Count < numberOfRooms) {
Room currentRoom = roomsToCreate.Dequeue ();
this.rooms [currentRoom.roomCoordinate.x, currentRoom.roomCoordinate.y] = currentRoom;
createdRooms.Add (currentRoom);
AddNeighbors (currentRoom, roomsToCreate);
}
int maximumDistanceToInitialRoom = 0;
Room finalRoom = null;
foreach (Room room in createdRooms) {
List<Vector2Int> neighborCoordinates = room.NeighborCoordinates ();
foreach (Vector2Int coordinate in neighborCoordinates) {
Room neighbor = this.rooms [coordinate.x, coordinate.y];
if (neighbor != null) {
room.Connect (neighbor);
}
}
room.PopulateObstacles (this.numberOfObstacles, this.possibleObstacleSizes);
room.PopulatePrefabs (this.numberOfEnemies, this.possibleEnemies);
int distanceToInitialRoom = Mathf.Abs (room.roomCoordinate.x - initialRoomCoordinate.x) + Mathf.Abs(room.roomCoordinate.y - initialRoomCoordinate.y);
if (distanceToInitialRoom > maximumDistanceToInitialRoom) {
maximumDistanceToInitialRoom = distanceToInitialRoom;
finalRoom = room;
}
}
GameObject[] goalPrefabs = { this.goalPrefab };
finalRoom.PopulatePrefabs(1, goalPrefabs);
return this.rooms [initialRoomCoordinate.x, initialRoomCoordinate.y];
}
private void AddNeighbors(Room currentRoom, Queue<Room> roomsToCreate) {
List<Vector2Int> neighborCoordinates = currentRoom.NeighborCoordinates ();
List<Vector2Int> availableNeighbors = new List<Vector2Int> ();
foreach (Vector2Int coordinate in neighborCoordinates) {
if (this.rooms[coordinate.x, coordinate.y] == null) {
availableNeighbors.Add (coordinate);
}
}
int numberOfNeighbors = (int)Random.Range (1, availableNeighbors.Count);
for (int neighborIndex = 0; neighborIndex < numberOfNeighbors; neighborIndex++) {
float randomNumber = Random.value;
float roomFrac = 1f / (float)availableNeighbors.Count;
Vector2Int chosenNeighbor = new Vector2Int(0, 0);
foreach (Vector2Int coordinate in availableNeighbors) {
if (randomNumber < roomFrac) {
chosenNeighbor = coordinate;
break;
} else {
roomFrac += 1f / (float)availableNeighbors.Count;
}
}
roomsToCreate.Enqueue (new Room(chosenNeighbor));
availableNeighbors.Remove (chosenNeighbor);
}
}
private void PrintGrid() {
for (int rowIndex = 0; rowIndex < this.rooms.GetLength (1); rowIndex++) {
string row = "";
for (int columnIndex = 0; columnIndex < this.rooms.GetLength (0); columnIndex++) {
if (this.rooms [columnIndex, rowIndex] == null) {
row += "X";
} else {
row += "R";
}
}
Debug.Log (row);
}
}
public void MoveToRoom(Room room) {
this.currentRoom = room;
}
public Room CurrentRoom() {
return this.currentRoom;
}
public void ResetDungeon() {
this.currentRoom = GenerateDungeon ();
}
}
and
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
public class Room
{
public Vector2Int roomCoordinate;
public Dictionary<string, Room> neighbors;
private string[,] population;
private Dictionary<string, GameObject> name2Prefab;
public Room (int xCoordinate, int yCoordinate)
{
this.roomCoordinate = new Vector2Int (xCoordinate, yCoordinate);
this.neighbors = new Dictionary<string, Room> ();
this.population = new string[18, 10];
for (int xIndex = 0; xIndex < 18; xIndex += 1) {
for (int yIndex = 0; yIndex < 10; yIndex += 1) {
this.population [xIndex, yIndex] = "";
}
}
this.population [8, 5] = "Player";
this.name2Prefab = new Dictionary<string, GameObject> ();
}
public Room (Vector2Int roomCoordinate)
{
this.roomCoordinate = roomCoordinate;
this.neighbors = new Dictionary<string, Room> ();
this.population = new string[18, 10];
for (int xIndex = 0; xIndex < 18; xIndex += 1) {
for (int yIndex = 0; yIndex < 10; yIndex += 1) {
this.population [xIndex, yIndex] = "";
}
}
this.population [8, 5] = "Player";
this.name2Prefab = new Dictionary<string, GameObject> ();
}
public List<Vector2Int> NeighborCoordinates () {
List<Vector2Int> neighborCoordinates = new List<Vector2Int> ();
neighborCoordinates.Add (new Vector2Int(this.roomCoordinate.x, this.roomCoordinate.y - 1));
neighborCoordinates.Add (new Vector2Int(this.roomCoordinate.x + 1, this.roomCoordinate.y));
neighborCoordinates.Add (new Vector2Int(this.roomCoordinate.x, this.roomCoordinate.y + 1));
neighborCoordinates.Add (new Vector2Int(this.roomCoordinate.x - 1, this.roomCoordinate.y));
return neighborCoordinates;
}
public void Connect (Room neighbor) {
string direction = "";
if (neighbor.roomCoordinate.y < this.roomCoordinate.y) {
direction = "N";
}
if (neighbor.roomCoordinate.x > this.roomCoordinate.x) {
direction = "E";
}
if (neighbor.roomCoordinate.y > this.roomCoordinate.y) {
direction = "S";
}
if (neighbor.roomCoordinate.x < this.roomCoordinate.x) {
direction = "W";
}
this.neighbors.Add (direction, neighbor);
}
public string PrefabName () {
string name = "Room_";
foreach (KeyValuePair<string, Room> neighborPair in neighbors) {
name += neighborPair.Key;
}
return name;
}
public Room Neighbor (string direction) {
return this.neighbors [direction];
}
public void PopulateObstacles (int numberOfObstacles, Vector2Int[] possibleSizes) {
for (int obstacleIndex = 0; obstacleIndex < numberOfObstacles; obstacleIndex += 1) {
int sizeIndex = Random.Range (0, possibleSizes.Length);
Vector2Int regionSize = possibleSizes [sizeIndex];
List<Vector2Int> region = FindFreeRegion (regionSize);
foreach (Vector2Int coordinate in region) {
this.population [coordinate.x, coordinate.y] = "Obstacle";
}
}
}
public void PopulatePrefabs (int numberOfPrefabs, GameObject[] possiblePrefabs) {
for (int prefabIndex = 0; prefabIndex < numberOfPrefabs; prefabIndex += 1) {
int choiceIndex = Random.Range (0, possiblePrefabs.Length);
GameObject prefab = possiblePrefabs [choiceIndex];
List<Vector2Int> region = FindFreeRegion (new Vector2Int(1, 1));
this.population [region[0].x, region[0].y] = prefab.name;
this.name2Prefab [prefab.name] = prefab;
}
}
private List<Vector2Int> FindFreeRegion (Vector2Int sizeInTiles) {
List<Vector2Int> region = new List<Vector2Int>();
do {
region.Clear();
Vector2Int centerTile = new Vector2Int(UnityEngine.Random.Range(2, 18 - 3), UnityEngine.Random.Range(2, 10 - 3));
region.Add(centerTile);
int initialXCoordinate = (centerTile.x - (int)Mathf.Floor(sizeInTiles.x / 2));
int initialYCoordinate = (centerTile.y - (int)Mathf.Floor(sizeInTiles.y / 2));
for (int xCoordinate = initialXCoordinate; xCoordinate < initialXCoordinate + sizeInTiles.x; xCoordinate += 1) {
for (int yCoordinate = initialYCoordinate; yCoordinate < initialYCoordinate + sizeInTiles.y; yCoordinate += 1) {
region.Add(new Vector2Int(xCoordinate, yCoordinate));
}
}
} while(!IsFree (region));
return region;
}
private bool IsFree (List<Vector2Int> region) {
foreach (Vector2Int tile in region) {
if (this.population [tile.x, tile.y] != "") {
return false;
}
}
return true;
}
public void AddPopulationToTilemap (Tilemap tilemap, TileBase obstacleTile) {
for (int xIndex = 0; xIndex < 18; xIndex += 1) {
for (int yIndex = 0; yIndex < 10; yIndex += 1) {
if (this.population [xIndex, yIndex] == "Obstacle") {
tilemap.SetTile (new Vector3Int (xIndex - 9, yIndex - 5, 0), obstacleTile);
} else if (this.population [xIndex, yIndex] != "" && this.population [xIndex, yIndex] != "Player") {
GameObject prefab = GameObject.Instantiate (this.name2Prefab[this.population [xIndex, yIndex]]);
prefab.transform.position = new Vector2 (xIndex - 9 + 0.5f, yIndex - 5 + 0.5f);
}
}
}
}
}
any help would be awesome even if you can point me in the direction to a how to.
Nice procedural dungeon generator! Just as a suggestion, could you cache the first room at the beginning when you are generating the dungeon? Then you can grab the initialRoomForPlayerSpawn coordinates/ position as a reference point for the character placement.
Room initialRoomForPlayerSpawn = null;
while (roomsToCreate.Count > 0 && createdRooms.Count < numberOfRooms) {
Room currentRoom = roomsToCreate.Dequeue ();
this.rooms [currentRoom.roomCoordinate.x, currentRoom.roomCoordinate.y] = currentRoom;
createdRooms.Add (currentRoom);
AddNeighbors (currentRoom, roomsToCreate);
/* Cache First Room */
if(createdRooms != null && createdRooms.Count <= 1) {
initialRoomForPlayerSpawn = currentRoom;
}
}
I've looked through the code and tried different approaches multiple times, but i just can't seem to get it to work.
It works properly twice, then its stops working properly the third time.
I want 1 object to be instantiated each time, but instead on the third time it spawns 30, which is bad.
I want it to spawn 1 object each time.
So i used this script.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Attack : MonoBehaviour {
public Transform playerPos = null;
private float playerDist;
private GameObject projectileEnemyClone;
public GameObject projectileEnemyPrefab;
private float kickBack = 10;
private Rigidbody rb;
private int bulletCount = 0;
private bool canshoot = true;
void Start()
{
rb = GetComponent<Rigidbody>();
}
private void Shoot()
{
if (canshoot == true)
{
projectileEnemyClone = Instantiate(projectileEnemyPrefab, transform.position, Quaternion.identity) as GameObject;
canshoot = false;
}
}
private void Respawn()
{
canshoot = true; ;
}
private void ShootLeft()
{
Shoot();
projectileEnemyClone.transform.position = new Vector3(transform.position.x - 1, transform.position.y, transform.position.z);
projectileEnemyClone.GetComponent<Rigidbody>().AddForce(transform.right * -10);
kickBack *= -1;
rb.AddForce(transform.right * kickBack);
Destroy(projectileEnemyClone, 1);
if (!canshoot)
{
Invoke("Respawn", 2);
}
}
private void ShootRight()
{
Shoot();
projectileEnemyClone.transform.position = new Vector3(transform.position.x + 1, transform.position.y, transform.position.z);
projectileEnemyClone.GetComponent<Rigidbody>().AddForce(transform.right * 10);
rb.AddForce(transform.right * kickBack);
Destroy(projectileEnemyClone, 1);
Invoke("Respawn", 2);
}
void Update () {
playerDist = playerPos.position.x - transform.position.x;
if (playerDist <= (3) && playerDist >= (-3))
{
if (playerDist < (0))
{
Invoke("ShootLeft", 1);
}
else
{
Invoke("ShootRight", 1);
}
}
}
}
Don't use Invoke(), you should create a timer that controls your Shoot() function.
float shootCooldown = 0.1f;
float shootTimer = 0;
bool justShot = false;
void Update()
{
if(!canShoot)
{
shootTimer += Time.deltaTime;
if(shootTimer >= shootCooldown)
{
shootTimer = 0;
canShoot = true;
}
}
}
void Shoot()
{
if(canShoot)
{
Shoot();
canShoot = false;
}
}
My unity player keeps on freezing after a while, I know what script is causing it (if it is indeed a script that is causing it). since there's only one script I've edited when it started freezing. But I can't figure out WHY it is freezing!
Here is the script that is causing it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GameManager : MonoBehaviour {
//public GameObject allPlayersPrefab;
public GameObject allPlayers;
public Transform playerRed;
public Transform playerGreen;
//public Transform playerPurple;
//public Transform playerYellow;
//Tail redTail;
//Tail greenTail;
//Tail purpleTail;
//Tail yellowTail;
public float secondsBetweenGaps = 2f;
public float secondsToGap = .25f;
public float snakeSpeed = 3f;
public float turnSpeed = 200f;
public int biggerPickupDuration = 3;
public int smallerPickupDuration = 3;
public int speedPickupDuration = 2;
public int invinciblePickupDuration = 3;
public int maxPickups = 3;
public int spawnPickupThreshold = 5;
private GameObject[] currPickups;
public GameObject[] pickupTypes;
public Transform pickupsParent;
public int players = 2;
[HideInInspector]
public int alive;
public bool enableKeys = false;
public GameObject prefabTail;
public GameObject settingsMenu;
public GameObject startingPanel;
public Text scoreText;
public Text radiusText;
public Text speedText;
public Text winText;
private bool hasEnded = false;
[HideInInspector]
public bool playerWon = false;
public bool running;
public Snake[] snakes;
ButtonManager buttonManager;
Pickup[] pickups;
void Start() {
//InstantiateNewPlayers();
playerRed = allPlayers.transform.FindChild("Red");
playerGreen = allPlayers.transform.FindChild("Green");
snakes = allPlayers.GetComponentsInChildren<Snake>(true);
alive = players;
//redTail = playerRed.GetComponentInChildren<Tail>();
//greenTail = playerGreen.GetComponentInChildren<Tail>();
//purpleTail = playerPurple.GetComponentInChildren<Tail>();
//yellowTail = playerYellow.GetComponentInChildren<Tail>();
buttonManager = FindObjectOfType<ButtonManager>();
pickups = FindObjectsOfType<Pickup>();
playerRed.gameObject.SetActive(false);
playerGreen.gameObject.SetActive(false);
//playerPurple.gameObject.SetActive(false);
//playerYellow.gameObject.SetActive(false);
winText.enabled = false;
foreach(Snake snake in snakes) {
snake.scoreText.enabled = false;
}
}
void Update() {
if(Input.GetKey(KeyCode.Escape)) {
foreach(Snake snake in snakes) {
snake.score = 0;
snake.scoreText.text = "0";
}
buttonManager.anima.Play("BackToSettings");
playerWon = true;
ResetGame();
buttonManager.restartButt.gameObject.SetActive(false);
buttonManager.StopAllCoroutines();
buttonManager.countDownText.enabled = false;
winText.enabled = false;
foreach(Snake snake in snakes) {
snake.scoreText.enabled = false;
}
}
if(alive == 1 && !hasEnded) {
Transform lastPlayer;
foreach(Snake child in snakes) {
if(!child.dead) {
lastPlayer = child.transform.parent;
if(child.score >= int.Parse(scoreText.text)) {
Win(lastPlayer.name);
AllPlayersDead();
} else
AllPlayersDead();
break;
}
}
}
if(alive == 0) {
if(hasEnded)
return;
buttonManager.restartButt.gameObject.SetActive(true);
hasEnded = true;
running = false;
}
foreach(Snake child in snakes) {
if(child.score >= int.Parse(scoreText.text)) {
AllPlayersDead();
Win(child.transform.parent.name);
}
}
}
public void AllPlayersDead() {
if(hasEnded)
return;
buttonManager.restartButt.gameObject.SetActive(true);
hasEnded = true;
running = false;
}
void Win(string winningPlayer) {
foreach(Snake snake in snakes) {
snake.score = 0;
snake.scoreText.text = "0";
}
Debug.Log("Win got called");
winText.gameObject.SetActive(true);
winText.enabled = true;
winText.text = winningPlayer + " wins!";
playerWon = true;
running = false;
}
public void PlayerDied() {
foreach(Snake child in snakes) {
if(!child.dead) {
child.score += 1;
}
}
}
public IEnumerator SpawnPickups() {
while(enabled) {
Debug.Log("SpawnPickups running...");
if(running) {
if(pickupsParent.childCount < maxPickups) {
int type = Random.Range(0, pickupTypes.Length);
float X = Random.Range(-7f, 7f);
float Y = Random.Range(-3f, 3f);
Vector3 spawnPos = new Vector3(X, Y, 0);
/*GameObject newPickup = */Instantiate(pickupTypes[type], spawnPos, Quaternion.Euler(0, 0, 0), pickupsParent);
Debug.Log("SpawnPickups instantiated new pickup...");
yield return new WaitForSeconds(spawnPickupThreshold);
}
}
}
}
public void ResetGame() {
Debug.Log("Resetting everything...");
for(int i = 0; i < players; i++) {
Transform currPlayer = allPlayers.transform.GetChild(i);
currPlayer.GetComponentInChildren<Tail>().points.Clear();
currPlayer.GetComponentInChildren<Snake>().dead = false;
currPlayer.GetComponentInChildren<Snake>().invincible = false;
currPlayer.GetComponentInChildren<Snake>().posInformer.position = new Vector3(-20, 0, 0);
if(playerWon) {
currPlayer.GetComponentInChildren<Snake>().score = 0;
playerWon = false;
}
//currPlayer.GetComponentInChildren<LineRenderer>().positionCount = 0;
currPlayer.GetComponentInChildren<LineRenderer>().numPositions = 0;
List<Vector2> list = new List<Vector2>();
list.Add(new Vector2(0, 5));
list.Add(new Vector2(0, 6));
StopAllCoroutines();
for(int i2 = 0; i2 < pickups.Length; i2++) {
pickups[i2].StopAllCoroutines();
}
foreach(Transform pickup in pickupsParent) {
Destroy(pickup.gameObject);
}
currPlayer.GetComponentInChildren<EdgeCollider2D>().points = list.ToArray();
foreach(Transform child in currPlayer) {
if(child.CompareTag("PrefabTail")) {
Destroy(child.gameObject);
}
}
currPlayer.gameObject.SetActive(false);
currPlayer.GetComponentInChildren<Tail>().enabled = true;
Destroy(GameObject.FindWithTag("PrefabTail"));
turnSpeed = int.Parse(radiusText.text) * 10;
snakeSpeed = float.Parse(speedText.text);
alive = players;
hasEnded = false;
running = false;
}
Debug.Log("Resetting done.");
}
}
I do have a small suspection that the freezing has something to do with the SpawnPickups method and/or the part where it destroys the pickups in the ResetGame method.
Thanks!
Your method SpawnPickups is doing this.
When you call this coroutine, and enable is true and running is false, you never reach a "yield" instruction, so your while(enabled) is indeed a while(true)
Coroutines are not threads, they run on the main thread and if you block a coroutine like this one, you are blocking the game.
public IEnumerator SpawnPickups() {
while(enabled) {
Debug.Log("SpawnPickups running...");
if(running) {
if(pickupsParent.childCount < maxPickups) {
int type = Random.Range(0, pickupTypes.Length);
float X = Random.Range(-7f, 7f);
float Y = Random.Range(-3f, 3f);
Vector3 spawnPos = new Vector3(X, Y, 0);
/*GameObject newPickup = */Instantiate(pickupTypes[type], spawnPos, Quaternion.Euler(0, 0, 0), pickupsParent);
Debug.Log("SpawnPickups instantiated new pickup...");
yield return new WaitForSeconds(spawnPickupThreshold);
}
//Here you need some yield in case running is true but you reached maxPickups (this one is not necessary if you put the next one)
}
//Here you need some yield in case running is false
//yield return null; //this should be enough to prevent your game from freezing
}
}