在固定位置生成 2D 游戏

Posted

技术标签:

【中文标题】在固定位置生成 2D 游戏【英文标题】:Spawn in a fix position 2D Game 【发布时间】:2020-04-20 14:33:11 【问题描述】:

我正在尝试制作多人游戏,但我遇到了生成预制件的问题。我希望这个预制件在 2 个固定位置生成,但我不明白为什么我的脚本不起作用,因为当我开始游戏时,对象会在一个位置生成。我创建了一个空游戏对象(我将其命名为 Spawner 并添加了脚本)并添加了 2 个游戏对象( Position1 、 Position2 )作为 Childs。预制件在 Spawner 的位置生成,而不是在 1 和 2 位置。 这是我使用的脚本。我还必须添加 PhotonView 和 Photon Transform 吗?和 PunRPC 有什么关系?

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

public class SpawnPosition : MonoBehaviour

    public GameObject[] powersPrefab;
    public Transform[] points;
    public float beat= (60/130)*2;
    private float timer;




    // Start is called before the first frame update
    void Start()
    
        
    

    // Update is called once per frame
    void Update()
    
        if (timer > beat)
        
            GameObject powers = Instantiate(powersPrefab[Random.Range(0, 2)]);
            powers.transform.localPosition = Vector2.zero;
            timer -= beat;

        
        timer += Time.deltaTime;
    

【问题讨论】:

你总是设置powers.transform.localPosition = Vector2.zero,因为对象是在没有父级的情况下在根级别实例化的,这等于设置它的绝对位置......你总是将它设置为Unity原点......跨度> 所以我应该删除这行代码? 这不会有任何区别,因为这在默认情况下无论如何都会在 Instantiate 中发生......我看不到你在这里使用生成器的子对象的任何位置......而且:如果这是用于多人游戏...您当前仅在一个客户端上生成对象,而没有告诉其他客户端生成了某些东西...没有光子专家,但您需要 NetworkInstantiate 之类的东西.. 【参考方案1】:

你总是设置

powers.transform.localPosition = Vector2.zero

对象在没有父级的情况下在根级别实例化,这等于设置其绝对位置....您始终将其设置为 Unity 原点。


您可能想在points 中的一个元素的位置生成它,例如:

var powers = Instantiate(
    powersPrefab[Random.Range(0, powersPrefab.Length)], 
    points[Random.Range(0, points.Length)].position, 
    Quaternion.identity
);

请参阅Instantiate 了解可用的重载。


但是,正如您所说,这是针对多人游戏的,因此您不应该使用 Instantiate 根本,因为这只会在此客户端上生成此对象,而不会在其他客户端上生成此对象。您或许应该确保这个 spawner 只在您的一个客户端上运行,并改用 PhotonNetwork.Instantiate

类似的东西,例如

public class SpawnPosition : MonoBehaviour

    public GameObject[] powersPrefab;
    public Transform[] points;
    public float beat= (60/130)*2;
    private float timer;

    // Update is called once per frame
    void Update()
    
        // only run this if you are the master client
        if(!PhotonNetwork.isMasterClient) return;

        if (timer > beat)
        
            // spawn the prefab object over network
            // Note: This requires you to also reference the prefabs in Photon as spawnable object
            Instantiate(
                powersPrefab[Random.Range(0, 2)].name, 
                points[Random.Range(0, points.Length)].position, 
                Quaternion.identity, 
                0
            );
            timer -= beat;
        
        timer += Time.deltaTime;
    

【讨论】:

【参考方案2】:

这应该可以工作

void Update() 
        if (timer > beat) 
            GameObject powers = Instantiate(powersPrefab[Random.Range(0, 2)]);
            powers.transform.localPosition = points[Random.Range(0, points.Length)].position;
            timer -= beat;

        
        timer += Time.deltaTime;
    

您没有分配正确的位置,并且由于它们没有父级power.transform.position = Vector2.zero 意味着电源的全局位置将始终为 0,0,0。所以你必须像我上面写的那样分配它,而且它也是随机的。

【讨论】:

我收到此错误:IndexOutOfRangeException:索引超出了数组的范围。 SpawnPosition.Update () 它指的是 GameObject powers = Instantiate(powersPrefab[Random.Range(0, 2)]); --------我应该改变什么? 看起来 powersPrefab 数组是空的,或者只有 1 个对象,所以用你的预制件从统一检查器中填充它 另外我建议你总是将容器对象(例如数组或列表)命名为复数,最好是 GameObject powerPrefabs[] 以便更好地理解代码

以上是关于在固定位置生成 2D 游戏的主要内容,如果未能解决你的问题,请参考以下文章

3D游戏中镜头的运用

gtk 固定窗口位置

钻石和玻璃球游戏(钻石位置固定)

钻石和玻璃球游戏(钻石位置固定)

钻石和玻璃球游戏(钻石位置不固定)

钻石和玻璃球游戏(钻石位置不固定)