You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中创建带子物体的UI元素数组及卡牌实例化问题求助

卡牌游戏随机生成问题:实例化卡牌丢失子物体

问题描述

开发卡牌游戏的随机生成系统,需求是点击按钮时实例化随机卡牌。卡牌结构为UI Image作为父物体,附带文本子物体,但遇到以下问题:

  • 使用GameObject类型数组时无法正常引用(拖拽赋值无效)
  • 改用Image类型数组后,实例化操作仅生成Image本身,文本子物体不会被同步创建

原始代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CardMasterScript : MonoBehaviour
{
    public Image[] CardArray = new Image[8];
    public float RollNumber;
    public Canvas ParentCanvas;

    public void RollCard()
    {
        RollNumber = Random.Range(0.1f, 100);

        Debug.Log("Number Rolled: " + RollNumber);

        if(RollNumber <= 47.9)
        {
            var card = Instantiate(CardArray[0]);
            card.transform.SetParent(ParentCanvas.transform);
            Destroy(card, 0.5f);
        } else if(RollNumber > 47.9 && RollNumber <= 77.9)
        {
            var card = Instantiate(CardArray[1]);
            card.transform.SetParent(ParentCanvas.transform);
            Destroy(card, 0.5f);
        } else if( RollNumber > 77.9 && RollNumber <= 87.9)
        {
            var card = Instantiate(CardArray[2]);
            card.transform.SetParent(ParentCanvas.transform);
            Destroy(card, 0.5f);
        } else if(RollNumber > 87.9 && RollNumber <= 94.9)
        {
            var card = Instantiate(CardArray[3]);
            card.transform.SetParent(ParentCanvas.transform);
            Destroy(card, 0.5f);
        } else if(RollNumber > 94.9 && RollNumber <= 97.9)
        {
            var card = Instantiate(CardArray[4]);
            card.transform.SetParent(ParentCanvas.transform);
            Destroy(card, 0.5f);
        } else if(RollNumber > 97.9 && RollNumber <= 99.4)
        {
            var card = Instantiate(CardArray[5]);
            card.transform.SetParent(ParentCanvas.transform);
            Destroy(card, 0.5f);
        } else if(RollNumber > 99.4 && RollNumber <= 99.9)
        {
            var card = Instantiate(CardArray[6]);
            card.transform.SetParent(ParentCanvas.transform);
            Destroy(card, 0.5f);
        } else if (RollNumber > 99.9 && RollNumber <= 100)
        {
            var card = Instantiate(CardArray[7]);
            card.transform.SetParent(ParentCanvas.transform);
            Destroy(card, 0.5f);
        }
    }
}

解决方案

核心问题:Instantiate传入Image组件时,只会复制该组件本身,不会复制其所在GameObject的子物体。正确做法是实例化卡牌的根GameObject,而非单独的Image组件。

1. 修改数组类型

将Image[] CardArray改为GameObject[] CardArray,存储整个卡牌的根GameObject(包含Image和文本子物体)。

2. 调整实例化逻辑

实例化GameObject时,直接传入预制体根对象,并设置父物体时关闭世界坐标继承,避免UI位置错乱。

优化后代码

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CardMasterScript : MonoBehaviour
{
    // 存储卡牌的根GameObject,包含所有子物体
    public GameObject[] CardArray = new GameObject[8];
    public float RollNumber;
    public Canvas ParentCanvas;

    public void RollCard()
    {
        RollNumber = Random.Range(0.1f, 100);
        Debug.Log("Number Rolled: " + RollNumber);

        int cardIndex = GetCardIndexByRoll(RollNumber);
        if (cardIndex >= 0 && cardIndex < CardArray.Length)
        {
            // 实例化整个卡牌GameObject,自动包含所有子物体
            var cardObj = Instantiate(CardArray[cardIndex], ParentCanvas.transform, false);
            // 若需操作Image组件,可通过GetComponent获取
            // var cardImage = cardObj.GetComponent<Image>();
            Destroy(cardObj, 0.5f);
        }
    }

    // 抽离概率判断逻辑,提升代码可维护性
    private int GetCardIndexByRoll(float rollValue)
    {
        if (rollValue <= 47.9) return 0;
        else if (rollValue <= 77.9) return 1;
        else if (rollValue <= 87.9) return 2;
        else if (rollValue <= 94.9) return 3;
        else if (rollValue <= 97.9) return 4;
        else if (rollValue <= 99.4) return 5;
        else if (rollValue <= 99.9) return 6;
        else if (rollValue <= 100) return 7;
        return -1;
    }
}

额外注意事项

  • 在Unity编辑器中,将每个卡牌的根GameObject拖拽到CardArray数组中,确保每个元素包含完整的卡牌层级
  • 实例化时第三个参数设为false,让UI自动适配Canvas的缩放和布局,避免位置偏移
  • 抽离概率判断逻辑后,后续修改概率或新增卡牌时只需调整GetCardIndexByRoll方法即可

内容的提问来源于stack exchange,提问作者DatBoiChonkey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 10:15:36