Игра Unity c # mario

#c# #unity3d

#c# #unity-игровой движок

Вопрос:

Я слежу за этой серией YouTube, в которой создается игра Unity 3D Mario. ( https://www.youtube.com/watch?v=vjL3S5dKLN4amp;index=6amp;list=PLZ1b66Z1KFKgm4QrzZ11jfaeHVaWHSHW7 )

Итак, я пытаюсь воссоздать сценарий «спускаясь по трубе», как в игре Mario. Я создаю аниматор и пытаюсь запустить анимацию с помощью скрипта C # при нажатии клавиши вниз.

1. Проблема: Этот парень пишет свои скрипты на Javascript, и, по-видимому, моя версия Unity больше не поддерживает js, поэтому мне нужно написать это на C # (и я предпочитаю писать это на C #).

В принципе, мне нужно преобразовать этот js в c#:

 var PipeEntry : GameObject;
var StoodOn : int;


function OnTriggerEnter (col : Collider) {
    StoodOn = 1;
}

function OnTriggerExit (col : Collider) {
    StoodOn = 0;
}


function Update () {
    if (Input.GetButtonDown("GoDown")) {
        if (StoodOn == 1) {
            //GameObject.Find("FPSController").GetComponent("FirstPersonController").enabled=false;
            transform.position = Vector3(0, -1000, 0);
            WaitingForPipe();
        }
    }
}

function WaitingForPipe () {
    PipeEntry.GetComponent("Animator").enabled=true;
    yield WaitForSeconds(2);
    PipeEntry.GetComponent("Animator").enabled=false;
    //GameObject.Find("FPSController").GetComponent("FirstPersonController").enabled=true;
}
  

2. МОЙ КОД

Мой скрипт в настоящее время выглядит следующим образом:

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

// 
using UnityStandardAssets.Characters.FirstPerson;

public class PipeEntry : MonoBehaviour
{
    public GameObject pipe_entry;
    public int StoodOn;
    public int has_run = 0;
    public int waiting_pipe = 0;
    public int waiting_pipe_animation = 0;

    IEnumerator OnTriggerEnter(Collider col)
    {
        StoodOn = 1;
        yield return StoodOn;
    }

    IEnumerator OnTriggerExit(Collider col)
    {
        StoodOn = 0;
        yield return StoodOn;
    }

    IEnumerator WaitPipeAnimation()
    {
        waiting_pipe_animation = 1;
        yield return new WaitForSeconds(2);

    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetButtonDown("PipeDown"))
        {
            if (StoodOn == 1)
            {
                // Freeze player
                //GameObject.Find("Player").GetComponent<FirstPersonController>().enabled = false;
                transform.position = new Vector3(0, -1000, 0);
                WaitingForPipe();
                has_run = 1;
            }
        }
    }

    public void WaitingForPipe()
    {
        pipe_entry.GetComponent<Animator>().enabled = true;
        WaitPipeAnimation();
        pipe_entry.GetComponent<Animator>().enabled = false;
        waiting_pipe = 1;
        //GameObject.Find("Player").GetComponent<FirstPersonController>().enabled = true;
    }

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

    }
}
  

3. Факты

  • Анимация работает хорошо, если запускается непосредственно из Unity, поэтому скрипт не работает.

  • Я установил некоторые переменные отладки, которые также имеют значение 1, где скрипт прерывается, и waiting_pipe_animation является единственным, который не достигает.

4. ОБНОВЛЕНИЕ — Итак, в основном основная проблема связана с этой функцией:

 yield return new WaitForSeconds(2);
  

Если я помещу ее в функцию void, я получу это:

Тело не может быть блоком итератора, потому что void не является типом интерфейса итератора.

Если я установлю для анимации значение true и никогда не верну ему значение false, это сработает, но не так, как ожидалось, потому что, очевидно, анимация длится вечно.

Комментарии:

1. Вы запускаете сопрограммы, используя StartCoroutine : docs.unity3d.com/Manual/Coroutines.html

Ответ №1:

1. Функции OnTriggerEnter и OnTriggerExit не возвращают IEnumerator и не являются сопрограммами.

 private void OnTriggerEnter(Collider col)
{
    StoodOn = 1;
}

private void OnTriggerExit(Collider col)
{
    StoodOn = 0;
}
  

2. Если у персонажа будет более одной анимации, я предлагаю вам создавать переходы между анимациями и создавать переменные для управления ими. Есть несколько полезных функций, таких как SetFloat, SetInteger, setBool, SetTrigger и так далее. Если нет, то включение и отключение аниматора, как вы это делали, будет в порядке вещей.

3. Как заявил Okeme Christian, ее необходимо использовать StartCoroutine("WaitPipeAnimation") для вызова вашей сопрограммы.

4. pipe_entry.GetComponent<Animator>().enabled = false; должна находиться внутри функции WaitPipeAnimation, потому что весь код вне нее все равно будет выполняться в том же фрейме. Таким образом, по сути, вы активируете и деактивируете аниматор в одном и том же кадре и не сможете увидеть анимацию.

 IEnumerator WaitPipeAnimation()
{
    waiting_pipe_animation = 1;
    yield return new WaitForSeconds(2);
    pipe_entry.GetComponent<Animator>().enabled = false;
}
  

Если вы хотите лучше понять, как это работает, пожалуйста, протестируйте приведенный ниже код:

 void Start()
{
    StartCoroutine("CoroutineTest");
    Debug.Log("3");
}

IEnumerator CoroutineTest()
{
    Debug.Log("1");
    yield return new WaitForSeconds(5f);
    Debug.Log("2");
}
  

Обратите внимание, что порядок печати в консоли будет «1», «3», «2».

Комментарии:

1. Спасибо за ответ! Сегодня меня нет, но я попробую это завтра и решу, сработает ли это.

Ответ №2:

Вы не можете вызвать сопрограмму как функцию. Вместо этого вы запускаете сопрограмму, подобную этой

    StartCoroutine("Fade"); 
  

Где Fade — это имя сопрограммы, поэтому в вашем случае вы будете запускать ее следующим образом

    StartCoroutine("WaitPipeAnimation")
  

Комментарии:

1. Спасибо за ваш ответ, смотрите обновленный (я отредактировал вопрос), поэтому я определил проблему, но я не знаю, как это исправить. Насчет того, что руководство старое — я в этом совсем новичок, и игра, которую я имею в виду, очень похожа на Mario, поэтому я подумал, что это руководство было бы идеальным для начала.