C# 如何在Unity上使用脚本滚动页面?

C# 如何在Unity上使用脚本滚动页面?,c#,unity3d,mobile,scroll,uiscrollview,C#,Unity3d,Mobile,Scroll,Uiscrollview,我想创建一个库存系统,我想用GUI.Button创建我的按钮。我像这样创建它们 void OnGUI() { GUI.Button(new Rect(0, 220, 100, 20), "Top-left"); GUI.Button(new Rect(120,220, 100, 20), "Top-right"); GUI.Button(new

我想创建一个库存系统,我想用GUI.Button创建我的按钮。我像这样创建它们

void OnGUI()
        {
            
            GUI.Button(new Rect(0, 220, 100, 20), "Top-left");
            GUI.Button(new Rect(120,220, 100, 20), "Top-right");
            GUI.Button(new Rect(0, 280, 100, 20), "Bottom-left");
            GUI.Button(new Rect(120, 280, 100, 20), "Bottom-right");
    
          
            
        }
    

我的问题是我不能移动它们。我的意思是我想把scrollrect添加到我的清单中。但即使我加上它,我的按钮也不会动。如何像普通按钮一样动态移动它,或者如何使用脚本滚动它们?谢谢您的帮助。

我认为代码是自我解释的,但我将一般地解释。在UI中创建滚动视图。并使用框架和图像作为子对象为插槽创建预设。 对于布局,请使用GridLayout组或从代码创建水平布局,然后在需要时更改位置。然后使用以下代码:

public class InventoryManager : MonoBehaviour
{
    [SerializeField] Transform content; //Where all panels will be hold. Scroll rect is parent of this object. This is content of scroll view.
    Transform foodPanel, healthPanel, drinkPanel; // These are just child of *content* add them at awake

    [SerializeField] GameObject slotPrefab; //Slot is a UI element with frame and as child have empty image.

    Transform activePanel; // Hold the active page value (Ex: food panel, drink panel etc.)

    public void CreateItem(Transform panelToInstantiate, Item itemToİnstantiate)
    {
        GameObject slot = Instantiate(slotPrefab, panelToInstantiate);
        slot.transform.GetChild(0).GetComponent<Image>().sprite = itemToİnstantiate.icon;
        slot.transform.GetChild(1).GetComponent<TextMeshProUGUI>().text = itemToİnstantiate.itemName; // If you want a label (optioanal)
        slot.transform.GetChild(2).GetComponent<TextMeshProUGUI>().text = itemToİnstantiate.itemCost.ToString(); // This is optional if you want a label
        if (itemToİnstantiate as Food != null) // This is food
        {
            Character.energyAmount += (itemToİnstantiate as Food).energyAmount;
        }
        else if (itemToİnstantiate as Drink != null) // This is drink
            Character.energy++;
    }

    public void ChangePage(Transform transform)
    {
        // This is just place holder if you have more complicated system change code according to it. Currently we have only 3 panel
        foodPanel.gameObject.SetActive(false);
        drinkPanel.gameObject.SetActive(false);
        healthPanel.gameObject.SetActive(false);

        if (transform == foodPanel)
            foodPanel.gameObject.SetActive(true);
        else if (transform == drinkPanel)
            foodPanel.gameObject.SetActive(true);
        else if (transform == healthPanel)
            foodPanel.gameObject.SetActive(true);
    }

    void ScrollToItem(GameObject slot)
    {
        content.parent.GetComponent<ScrollView>().ScrollTo(slot.GetComponent<VisualElement>()); // I am not sure if that will work. Didn't try.
    }

    // Got this from stackoverflow. @maksymuik https://stackoverflow.com/a/30769550/9969193
    public void SnapTo(RectTransform target)
    {
        Canvas.ForceUpdateCanvases();

        contentPanel.anchoredPosition =
            (Vector2)scrollRect.transform.InverseTransformPoint(contentPanel.position)
            - (Vector2)scrollRect.transform.InverseTransformPoint(target.position);
    }
}

public class Item : ScriptableObject // Test item class. Scriptable object
{
    public string itemName;
    public int itemCost;
    public Sprite icon;
}

public class Food : Item // Child of item class.
{
    public int energyAmount;
    public int deliciousness;
}

public class Drink : Item
{
    public bool isHot;
}
公共类InventoryManager:MonoBehavior
{
[SerializeField]Transform content;//将保存所有面板的位置。Scroll rect是此对象的父对象。这是Scroll view的内容。
转换foodPanel、healthPanel、drinkPanel;//它们只是*content*的子项,在唤醒时添加它们
[SerializeField]GameObject slotPrefab;//Slot是一个具有框架的UI元素,并且作为子元素具有空图像。
Transform activePanel;//保留活动页面值(例如:食物面板、饮料面板等)
public void CreateItem(将面板转换为安装状态,将项目项转换为安装状态)
{
GameObject slot=实例化(slotPrefab,paneltoinstate);
slot.transform.GetChild(0.GetComponent().sprite=itemToİnstatite.icon;
slot.transform.GetChild(1.GetComponent().text=itemToİnstatite.itemName;//如果需要标签(可选)
slot.transform.GetChild(2.GetComponent().text=itemToİnstatite.itemCost.ToString();//如果需要标签,这是可选的
if(itemToİnstatite as Food!=null)//这是食物
{
Character.energyAmount+=(作为食物的物品)。energyAmount;
}
else if(itemToİnstatite as Drink!=null)//这是饮料
字符.能量++;
}
公共无效更改页(转换)
{
//如果您有更复杂的系统更改代码,这只是占位符。目前我们只有3个面板
foodPanel.gameObject.SetActive(false);
drinkPanel.gameObject.SetActive(false);
healthPanel.gameObject.SetActive(false);
if(transform==foodPanel)
foodPanel.gameObject.SetActive(true);
else if(transform==drinkPanel)
foodPanel.gameObject.SetActive(true);
else if(transform==healthPanel)
foodPanel.gameObject.SetActive(true);
}
无效ScrollToItem(游戏对象槽)
{
content.parent.GetComponent().ScrollTo(slot.GetComponent());//我不确定这是否有效。没有尝试。
}
//从stackoverflow那里得到的。@maksymuikhttps://stackoverflow.com/a/30769550/9969193
公共无效快照对象(RectTransform目标)
{
Canvas.forceUpdateCanvas();
contentPanel.anchoredPosition=
(Vector2)scrollRect.transform.InverseTransformPoint(contentPanel.position)
-(矢量2)滚动直线变换逆变换点(目标位置);
}
}
公共类项:ScriptableObject//测试项类。脚本对象
{
公共字符串itemName;
公共成本;
公共精灵图标;
}
公共类食品:项目//项目类的子项。
{
公共能源山;
公共性;
}
公共类饮料:项目
{
公共图书馆;
}

这不是旧的用户界面吗?在新的UI系统中,GUI类仅用于编辑器。为什么不使用组件呢?它会自动设置滚动所需的所有内容。因为我会像inventory元素一样使用这些按钮,它们必须是动态的。我的意思是按钮编号必须取决于用户。所以我需要使用脚本创建它们。如果我使用脚本,即使我使用ScrollView,它们也不会移动。我在很多事情中使用了scroll view,scroll view支持动态(通过脚本)创建的元素。滚动视图可用于库存系统,您可以将其从脚本中移动。你在哪一部分有问题?因为如果你使用GUI,除非你处理得很好,否则在不同大小的屏幕上,你的应用程序看起来会很奇怪。如果您发布与此问题相关的所有代码,我们可以帮助您更清楚地了解。这是我的库存系统。此库存中有三个部分。食品,饮料和健康选项卡。当用户创建配置文件时,此库存将为空。但如果他从市场购买东西,则我的库存系统必须创建一个按钮,并且必须将食物的图像放在按钮内。然后,如果他从市场购买另一种食物,则必须再次创建一个按钮。并且,您可以使用脚本向下滚动。这是我上传的库存图片,因为我希望你们能轻松想象。顺便说一句,如果我有另一个选项来创建动态按钮,你也可以告诉我:)哦,兄弟,你真是救命恩人。非常感谢,我会试试的