i have a bit of a break from school so i’ve been on a coding streak.
i have an inventory with 50 items. i might reduce it - there are party members in my RPG after all, whose inventory you can utilize - but for now, that’s a decent estimate. i know i can add a script to each text field that 1) highlights the text when you mouse over and 2) brings up a menu with buttons when you right click (also might have some functionality for loot containers and stores). but this would mean adding the script 50 times to 50 separate items. i don’t want to slow the fps down to a crawl.
is there any way to use a single script that loops through the text fields and does this somehow? i had something like that in Game Maker, but it’s such a different system and it is not possible to convert the code i used (which is good, because it was terrible code anyhow).
EDIT: here’s my code to look at:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
namespace CoS
{
public class InvLeftClickPrefab : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
public Transform prefab;
public Transform prefabparent;
public Text theText;
private Vector3 pos;
private void Start()
{
var pos = theText.transform.position;
//offset
pos.x += 5;
}
public void OnPointerEnter(PointerEventData eventData)
{
theText.color = Color.red; //Or however you do your color
}
public void OnPointerExit(PointerEventData eventData)
{
theText.color = Color.black; //Or however you do your color
}
//text fields are about 26 apart
private void OnGUI()
{
//if right click inventory item
if (Input.GetMouseButtonDown(1))
Instantiate(prefab, pos, Quaternion.identity);
}
}
}
as you can see, i don’t quite have the offset yet.
There’s nothing wrong with line 33 compiler-wise. Did you drag a reference into the public Transform prefab field?
You can also use Vector3.zero but what you have works fine.
As for adding the script in your original question, are you talking about run-time adding or do you perhaps want to write an Editor script that will bulk-add a particular thing to a whole bunch of your prefab assets?
basically, can i just add the script to the 50 text box components (would take me like 5 minutes of tedium), or is there a better way of doing this - like a way of just having one script added to some gui element one time instead of 1 script 50 times?
in other words, is 50 text boxes with a script attached to each going to slow down the game or doesn’t it matter?
First of all, there are also interfaces for pointerclick-events. So you can replace that old and ugly OnGUI which might turn out to be the most inefficient part of this script when adding this 50 times or more - remember that OnGUI can run multiple times per frame. When you’ve done that, the script itself should no longer have any huge impact on performance, even if you use it quite a lot.
Of course there are other ways that kind of match your idea. In order to get this to work, you’d want that one instance to be responsible for given feedback about the currently selected/clicked/hovered item.
You need to find out which slot you’re interacting with and get the components you want to access - of course you only need to do this when the target has changed or when a different kind of event has occured.
But that’s all up to you. I’d first try it the way you have it. The inventory slots should probably be a prefab - which reduces the number of scripts to attach to a single one.
You can then instantiate (or pool) the inventory slots and assign item data objects to them, that they’re going to show - this is flexible enough IMO.
is there a reliable way to test the fps, and what fps range would be bad/good? i read a thread where people were talking about how the editor’s fps checker was really way off, so i know i can’t trust that.
if i write a script that has the 50 text elements as references, then i can’t use the interfaces for checking mouse over. how would i do it instead? and would this even be a reasonable performance boost i guess is the question? maybe i’m looking for an excuse not to write another script, but if the “brute force” method doesn’t work (low fps) then i don’t have much choice.
You can use the profiler to check if there’s alot of overhead.
And testing your FPS in the editor is not much of a help anyway, as the editor comes itself with lots of overhead.
You could write a simple FPS script that displays current FPS, average, min and max and all the information you need.
As I said, for now I’d just test it.
If you want to implement that differently, you’d use some kind of raycasting to detect which UI element you’re hovering over. That’s what the event system already does. There’s also surely a property somewhere that allows you to get the current GO that is being pointed at, but well… the event system does already attempt to call these methods either way, so you can just use them.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
namespace CoS
{
public class InvLeftClickPrefab : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
public Transform prefab;
public Text theText;
private Vector3 pos;
private void Start()
{
var pos = theText.transform.position;
//offset
pos.x += 5;
}
public void OnPointerEnter(PointerEventData eventData)
{
theText.color = Color.red; //Or however you do your color
}
public void OnPointerExit(PointerEventData eventData)
{
theText.color = Color.black; //Or however you do your color
}
public void OnPointerClick(PointerEventData eventData)
{
if (eventData.button == PointerEventData.InputButton.Right)
{
Instantiate(prefab, pos, Quaternion.identity);
}
}
}
}
is instantiating the menu in the same place regardless of which text item it is attached to. confused about this.
edit: i even tried making pos public and setting the y position manually for each text box, but no matter what it just spawns in the same position.
edit2: even if i set vector3 to 0, 0, 0, it just ignores it and pastes the prefab in the same place.
edit3: my problems were because the prefab transform was assigned to not world space. now i changed it to world space and the y values are being modified correctly but i can’t even locate the prefab clones on screen … ugh, debugging hell
EDIT4: found out about transform.TransformPoint and its inverse, but i still can’t even locate the prefab objects in the game.
Hey there… if these context menus are the same, I would suggest that you just use one of them. If they have some differences, you can even turn on / off any child objects that may be relevant to an item in your inventory (that’s what I did in mine). Then, you needn’t instantiate it everytime, just use the reference and set the position.
As for you particular issue, if you want to go the path you’re currently on, I’d suggest that you don’t include a canvas with the prefab, but instead set the parent to your existing canvas when it’s instantiated.
You most-likely want to set the canvas (or another object in the canvas hierarchy) as parent when the object is created. Then you can move it relatively to that GO’s RectTransform, the anchoredPosition often turns out to be useful - because you can change a RectTransform’s anchor as you like and the child objects are way easier to position programmatically - for instance when you’re dealing with any dynamically positioned UI elements - which you want.
TransformPoint, TransformVector and TransformDirection (as well as the counter-parts) would only be interesting if you need to transform from world space to the current transform’s local space - which is not the case if I understand you correctly.