#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, поэтому я подумал, что это руководство было бы идеальным для начала.