C #: объекты в Unity отображаются в редакторе, но не отображаются на Android при подключенном скрипте - PullRequest
0 голосов
/ 01 марта 2019

Я строю маленький платформер, где игрок может собирать монеты.Поскольку в одной сцене иногда есть 100+ вращающихся монет, я решил рендерить только те монеты, которые находятся в непосредственной близости от игрока.Я имею в виду, это работало раньше - но на телефоне уровни с большим количеством монет, как правило, имеют некоторые лаги.С удаленными монетами, fps где на 60. Вот что я сделал:

public class AddCoinScript : MonoBehaviour
{
    public static int coinCounter = 0; // static cause we will only want ONE counter and not many instances of the coin value
    private Text coinText;
    private float disBetweenBirdyAndEnemy;

    private GameObject birdy;
    private Renderer rndr;
    private BoxCollider2D bx2D;
    private bool canAnimate = false;
    private float startAnimDistance = 20;
    private bool coinCollected = false;

void Start()
{
    coinText = GameObject.Find("Coin Text").GetComponent<Text>(); // Get the Coin Text Element
    coinText.text = "x" + coinCounter.ToString();

    birdy = GameObject.Find("Birdy"); 
    rndr = GetComponent<Renderer>();
    bx2D = GetComponent<BoxCollider2D>();

    rndr.enabled = true;
    bx2D.enabled = true;
}


void FixedUpdate()
{
     disBetweenBirdyAndEnemy = Vector3.Distance(birdy.transform.position, this.transform.position);

     if (disBetweenBirdyAndEnemy <= startAnimDistance)
     {
        if(!coinCollected)
        {
            rndr.enabled = true;
            bx2D.enabled = true;
        }

     }
     else
     {
        rndr.enabled = false;
        bx2D.enabled = false;
     }

    coinText.text = "x" + coinCounter.ToString();
}

void OnTriggerEnter2D(Collider2D col)
{
    if (col.gameObject.name == "Birdy") // detect collision with ground game object 
    {
        AddCoinAndRemoveHitBoxAndSprite();
    }


}

private void AddCoinAndRemoveHitBoxAndSprite()
{
    coinCounter++;
    coinCollected = true;
    rndr.enabled = false;
    bx2D.enabled = false;
    PlayCoinSound();
}

private void PlayCoinSound()
{
    AudioSource aS = GameObject.Find("GetCoinSound").GetComponent<AudioSource>();
    aS.Play();
}

}

Результат хороший.Монеты оказываются на сцене только тогда, когда игрок находится достаточно близко к ним.ОДНАКО, однажды развернутый на моем телефоне - монеты больше не рендерится.Как будто расстояние игроков до монет на моем телефоне отличается от расстояния на моем компьютере.

Я что-то упустил?

Спасибо

1 Ответ

0 голосов
/ 01 марта 2019

Я не вижу ничего явно неправильного в этом, но если равно , проверка расстояния прошла неправильно, вы можете попытаться отключить всю монету и включить ее, только если они на экране.

Решение, которое будет работать со всеми разрешениями, выглядит примерно так:

private bool IsOnScreen(Vector3 worldPosition)
{
    Vector3 screenPoint = camera.WorldToViewportPoint(worldPosition);

    return screenPoint.x > 0 
        && screenPoint.x < 1
        && screenPoint.y > 0
        && screenPoint.y < 1;
}

Отдельная проблема, которая может быть решена, заключается в том, что ваш скрипт для монет отвечает за слишком много вещей.Прямо сейчас каждая монета

  • Знает, сколько монет игрок имеет и может изменить это число
  • Знает и изменяет текст интерфейса для монет на старте
  • отвечает за включение / отключение своих собственных компонентов, когда вы можете просто уничтожить игровой объект, когда он собран
  • Находит звуковой игровой объект и воспроизводит звук

Из-за всех этих обязанностей вытруднее решать вопросы в этом классе.Подумайте о том, чтобы иметь некоторый класс CoinManager, который может отслеживать, сколько монет у игрока (вместо каждой отдельной монеты, зная о количестве монет).

Ваш класс может выглядеть примерно так

public class CoinManager : MonoBehaviour
{
    private Camera camera;
    [SerializeField] private AudioClip coinCollectedSound;
    [SerializeField] private AudioSource audioSource;
    [SerializeField] private List<CoinScript> coins;
    [SerializeField] private int coinCount;
    [SerializeField] private Text coinLabel;

    // This could be called by some spawner class that
    // adds coins to the scene
    public void AddCoin(CoinScript coin)
    {
        coins.Add(coin);
    }


    public void CoinCollected(CoinScript coin)
    {
        Destroy(coin.gameObject);
        coinCount++;
        audioSource.PlayOneShot(coinCollectedSound);
        // Alternatively, if you have a dedicated audio source 
        // for coin sounds you can just use audioSource.Play();
    }

    private void Update()
    {
        // Iterate over all the coins we know about
        foreach (var coin in coins)
        {
            // Now that we have a method that tells us whether a
            // coin is on the screen or not, we can enable and disable
            // all the coins at the same time in one place
            coin.transform.enabled = IsOnScreen(coin.transform.position);
        }
    }

    private void Awake()
    {
        // Gets the main camera in the scene
        // https://docs.unity3d.com/ScriptReference/Camera-main.html
        camera = Camera.main;
        coins = new List<CoinScript>();
    }

    private bool IsOnScreen(Vector3 worldPosition)
    {
        Vector3 screenPoint = camera.WorldToViewportPoint(worldPosition);

        return screenPoint.x > 0
               && screenPoint.x < 1
               && screenPoint.y > 0
               && screenPoint.y < 1;
    }
}

У меня нет Unity передо мной, так что вышесказанное находится на макушке моей головы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...