[英]Experiment and unity3D (coroutine, timer and specific conditions)
[已編輯] 大家好,
我正在修改的腳本“Follower”有一些問題(從 pathCreator Asset 獲取)。 我已經為它工作了幾個小時,但我現在受到我的知識和能力的限制。
這是我想要做的:
我的實驗參與者必須口頭回答與我的經驗相關的問題。 因此,為了避免習慣計時,我想在 FPS 字符停止時隨機化。 通過每 4、8 或 12 秒隨機停止,參與者將無法習慣計時。 如果 FPS 角色每 4 秒停止一次,參與者就會習慣它,並可能實施使我的結果產生偏差的響應策略。
所以我想做以下事情:
我希望能夠在有項目要展示的情況下多次執行此操作。 **對我的代碼的注釋不如之前顯示的解釋重要! **
總結一下:步行(隨機選擇 4 秒或 8 秒或 12 秒)-停止 4 秒(同時生成一個物體)-(4 秒結束)物體消失,FPS 再次開始步行(4 或 8 秒)或隨機選擇 12 秒)....
請記住:我不是編程專家,只知道如何在 C# 上做事,所以我無法將 Java 中的任何代碼轉換為 C#。 我基本上所做的就是復制粘貼代碼並盡力修改它以使其適合我的需要。 但我的能力有限。
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using PathCreation;
using UnityStandardAssets.Characters.FirstPerson;
// I AM USING THE PATHFOLLOWER SCRIPT FROM PATHCREATOR ASSET
// (i copy pasted it from the folder so i still have the original
// and can modify this one to add the timers and objects spawning conditions)
// Put this script on the FPScontroller
// Specify the pathCreator (object created with a unity assets and that is basicaly a draw line in the environnement that objects can follow)
// Depending on the end of path instruction, will either loop, reverse, or stop at the end of the path.
public class Follower : MonoBehaviour
{
public PathCreator pathCreator; //Object PathCreator to put specify in Unity (gameObject with specifics scripts)
public EndOfPathInstruction instructionFinChemin; //Variable that ask if the FPScontroller needs to stop/loop/reverse at the end of the path
[Range(1, 10)]
public float speedOfPlayer = 5; //Speed of the FPScontroller
float distanceTravelled; //Used to calculate the distance the FPS will need to walk
//Variable used to count time in secondes
private int secondsTimer;
private float timer = 0.0f;
public GameObject Clone;
public Transform SpawnArea; //Used to specify where the item will spawn
public GameObject ItemSpawning; //Object that will spawn (like a flower, a baloon or whatever)
private bool enter = false;
void Start()
{
if (pathCreator != null)
{
// Subscribed to the pathUpdated event so that we're notified if the path changes during the game
pathCreator.pathUpdated += OnPathChanged;
}
}
void Update()
{
//using this to get the time passed in secondes integer
timer += Time.time;
secondsTimer = (int)(timer % 60);
/*Condition : if the path exist and [4,8,12] secondes have not still passed, move the FPScharacter along the path
- HERE I NEED HELP : How do i do so it select randomly (after each stop)
that it will check for 4 - 8 or 12 secondes and not only for 4 secondes
- Like : Walk automatically along the path --> 4 secondes after --> Stop for 4 secondes and spawn an Object ---
--> Walk automatically --> 8 secondes after --> Stop for 4 secondes and spawn an object ... and so forth*/
if (pathCreator != null & (secondsTimer % 4 != 0))
{
distanceTravelled += speedOfPlayer * Time.deltaTime;
// Instruction permettant le déplacement de l'objet le long du path
transform.position = pathCreator.path.GetPointAtDistance(distanceTravelled, instructionFinChemin);
transform.rotation = pathCreator.path.GetRotationAtDistance(distanceTravelled, instructionFinChemin);
}
//If the path exist and [4,8,12] seconds have passed (I need it to be 4 or 8 or 12 secondes choosen randomly - as explained before in the comment of the script)
else if (pathCreator != null & (secondsTimer % 4 == 0))
{
//cloning my gameobject in the environnement so i can destroy it later. Dont know if i am doing mistakes here
Clone = (GameObject)Instantiate(ItemSpawning, SpawnArea.position, SpawnArea.rotation);
//Even if the FPScontriller is disabled in this loop, i still want him to watch and stay in the same direction
transform.position = pathCreator.path.GetPointAtDistance(distanceTravelled, instructionFinChemin);
transform.rotation = pathCreator.path.GetRotationAtDistance(distanceTravelled, instructionFinChemin);
//Disable de FPScontroller Movement Script
GameObject.Find("Player").GetComponent<FirstPersonController>().enabled = false;
//tried to use a coroutine so i can tell my script : wait for 4 secondes
//so using a coroutine with waitforsecondes but it isnt working
if (enter == false)
{
StartCoroutine(DelayLoadLevel());
}
}
Destroy(Clone);
GameObject.Find("Player").GetComponent<FirstPersonController>().enabled = true;
}
//fonction Coroutine pour delay le temps de redémarrage du personnage de 4 secondes
IEnumerator DelayLoadLevel()
{
enter = true;
Debug.Log("Your enter Coroutine at" + Time.time);
yield return new WaitForSeconds(4);
enter = false;
}
// If the path changes during the game, update the distance travelled so that the follower's position on the new path
// is as close as possible to its position on the old path
void OnPathChanged()
{
distanceTravelled = pathCreator.path.GetClosestDistanceAlongPath(transform.position);
}
}
現在唯一有效的是 FPS 角色沿路徑的移動(但它沒有考慮我的計時器,也沒有停止,也沒有產生或破壞物體)。 我還試圖實現一個包含我將在環境中生成的對象的游戲對象列表,但沒有成功 >>
有人可以幫我嗎? :D
好吧,
在你的幫助下,我設法讓我的角色移動了 4 秒,然后停止了 4 秒,然后移動了 4 秒,依此類推。
稍后我將進入 [4, 8, 12] 隨機化,因為現在這不是我的主要問題。
現在,我無法弄清楚為什么我的RigidBodyFPSController
每次停止時RigidBodyFPSController
旋轉到 Y = -180。 我嘗試在WaitforSeconds(4)
之前使用Rigidbody.freezeRotation = true
凍結它,但沒有成功。 我什至試圖禁用RigidBodyFPScontroller
但它做了一些奇怪的事情(屏幕跳躍和振動,就像 2 個移動功能之間存在沖突一樣)。
使用打印,我認為在調用 waitforSeconds(4) 時會發生 y = -180 的旋轉。 但我不知道為什么。
任何的想法 ?
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using PathCreation;
using UnityStandardAssets.Characters.FirstPerson;
// I AM USING THE PATHFOLLOWER SCRIPT FROM PATHCREATOR ASSET (modified to my will)
// Put this script on the FPScontroller
// Specify the pathCreator (object created with a unity assets and that is basicaly a draw line in the environnement that objects can follow)
// Depending on the end of path instruction, will either loop, reverse, or stop at the end of the path.
public class Follower : MonoBehaviour
{
public PathCreator pathCreator; //Object PathCreator to put specify in Unity (gameObject with specifics scripts)
public EndOfPathInstruction instructionFinChemin; //Variable that ask if the FPScontroller needs to stop/loop/reverse at the end of the path
[Range(1, 10)]
public float speedOfPlayer = 5; //Speed of the FPScontroller
float distanceTravelled; //Used to calculate the distance the FPS will need to walk
//Variable used to count time in secondes
private int timer = 0;
public GameObject Clone; //Trying to use this variable as the Clone of my Object that will spawn in the environnement and then will be destroyed
public Transform SpawnArea; //Used to specify where the item will spawn
public GameObject ItemSpawning; //Object that will spawn (like a flower, a baloon or whatever)
//Used to select randomly after each stop a seconde between 4, 8, 12
public int[] ListTiming;
static Random rnd = new Random();
/* private void Awake()
{
ListTiming = new int[3];
ListTiming[1] = 4;
ListTiming[1] = 8;
ListTiming[1] = 12;
int Timing = ListTiming[Random.Range(0, ListTiming.Length)];
}*/
void Start()
{
if (pathCreator != null)
{
// Subscribed to the pathUpdated event so that we're notified if the path changes during the game
pathCreator.pathUpdated += OnPathChanged;
}
//Used to count time and trigger stops
StartCoroutine(DelayLoadLevel());
}
void Update()
{
print(timer);
if (pathCreator != null & (timer % 4 != 0))
{
distanceTravelled += speedOfPlayer * Time.deltaTime; // se fait à chaque frame
// Instruction permettant le déplacement de l'objet le long du path
transform.position = pathCreator.path.GetPointAtDistance(distanceTravelled, instructionFinChemin);
// instruction pour permettre la rotation le long du path
transform.rotation = pathCreator.path.GetRotationAtDistance(distanceTravelled, instructionFinChemin);
//GameObject.Find("Player").GetComponent<FirstPersonController>().enabled = true;
}
}
//fonction Coroutine pour delay le temps de redémarrage du personnage de 4 secondes
IEnumerator DelayLoadLevel()
{
print("DelayLoadLevel");
while (true)
{
yield return new WaitForSeconds(1);
timer = timer + 1;
print("time = " + timer);
if (pathCreator != null && timer % 4 == 0)
{
print("time");
Debug.Log("Your enter DelayLoadLevel at " + timer);
//GameObject.Find("FPSController").GetComponent<RigidbodyFirstPersonController>().enabled = false;
Rigidbody.freezeRotation = true;
print("Entre dans wait for seconds : " + Time.time);
yield return new WaitForSeconds(4);
//GameObject.Find("FPSController").GetComponent<RigidbodyFirstPersonController>().enabled = true;
Rigidbody.freezeRotation = true;
print("Entre dans wait for seconds : " + Time.time);
}
}
}
// If the path changes during the game, update the distance travelled so that the follower's position on the new path
// is as close as possible to its position on the old path
void OnPathChanged()
{
distanceTravelled = pathCreator.path.GetClosestDistanceAlongPath(transform.position);
}
}
好吧,
我的問題是由之間的沖突引起的RigidBodyFPScontroller
腳本和PathCreator
腳本適用變換旋轉和運動。 禁用RigidBodyFPScontroller
腳本消除了這個問題。
現在,我需要弄清楚為什么當我的RigidBodyFPSController
停止時,它在空間中變得更高(從 Y = 0 到 Y ~0.8) - 請參閱下面的屏幕截圖。 為了描述行為,就像在它停止之前一樣, RigidBodyFPSController
在那個高度跳躍並凍結。 但也想不通為什么。
你可以嵌套協程。
[SerializeField] Follower follower;
List<GameObject> objectsToShow = new List<GameObject>();
IEnumerator Tick()
{
while (objectsToShow.Count > 0)
{
int[] seconds = { 4, 8, 12 };
int idx = Random.Range(0, seconds.Length);
int secondsToWait = seconds[idx];
yield return new WaitForSeconds(secondsToWait);
follower.Walk();
yield return new WaitForSeconds(secondsToWait);
follower.Stop();
}
}
大家好,
我設法做一些我想做的事情。 我忘記了 4-8-12 秒的隨機化,因為這對我來說很難實現。
但是你會發現其他任何東西都有效。 什么是腳本所做的是讓你選擇多少gameObject
要產卵多少transform
相關聯的gameObject
。 對於我的實驗,我必須首先顯示靜態項目 ( ìtemFixe
),然后是移動項目 ( ìtemMobile
),然后是混合項目,即靜態和移動項目 ( itemMixte
)。
這些項目將生成到您之前指定的轉換位置,並將在 4 秒后Destroy(instantiate...), 4)
)。 您的RigidBodyFPSController
將沿着使用 PATHCREATOR 統一資產創建的路徑移動。
這是我的腳本
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using PathCreation;
using UnityStandardAssets.Characters.FirstPerson;
// I AM USING THE PATHFOLLOWER SCRIPT FROM PATHCREATOR UNITY ASSET (modified to my will)
// All function besides what's inside the void update and void onPathchange functions have been made manually
// Put this script on the FPScontroller
// Specify the pathCreator (object created with a unity assets and that is basicaly a draw line using bezieLine in the environnement that objects can follow)
// Depending on the end of path instruction, will either loop, reverse, or stop at the end of the path.
public class Follower : MonoBehaviour
{
public PathCreator pathCreator; // Object PathCreator to put specify in Unity (gameObject with specifics scripts)
public EndOfPathInstruction instructionFinChemin; // Variable that ask if the FPScontroller needs to stop/loop/reverse at the end of the path
[Range(1, 10)]
public float speedOfPlayer = 5; // Speed of the FPScontroller
float distanceTravelled; // Used to calculate the distance the FPS will need to walk
// Variable used to count time in secondes
private int timer = 0;
// Used for spawning items (itemFixe) in a specific location (spawnPoint) using randomization
// 3 listes de gameObject (items fixe, mobile ou mixte) associés à 3 listes de trandform (spawnPoint fixe, mobile, mixte)
[SerializeField]
public GameObject[] itemFixe;
public GameObject[] itemMobile;
public GameObject[] itemMixte;
public Transform[] spawnPoint;
public Transform[] spawnPointMobile;
public Transform[] spawnPointMixte;
// Variables for the Spawn function :
// indexPosition used to check the spawnPoint[indexPosition] transform
// indexItem used to check the item[indexItemn] gameObject
// compteur used to check 'if' condition
private int indexPositionFixe = 0;
private int indexPositionMobile = 0;
private int indexPositionMixte = 0;
private int compteurFixe = 0;
private int compteurMobile = 0;
private int compteurMixte = 0;
private int indexItemFixe = 0;
private int indexItemMobile = 0;
private int indexItemMixte = 0;
void Start()
{
// Used to count time and trigger stops
StartCoroutine(DelayLoadLevel());
// To assure RigidBodyFPSController Script will not interfer with PathCreator Script
GameObject.Find("RigidBodyFPSController").GetComponent<RigidbodyFirstPersonController>().enabled = false;
// Randomize prefabs using the RandomizeArray function
RandomizeArray<GameObject>(itemFixe);
RandomizeArray<GameObject>(itemMobile);
RandomizeArray<GameObject>(itemMixte);
// Linked to the pathUpdated event : notified if the path changes during the game
if (pathCreator != null)
{
pathCreator.pathUpdated += OnPathChanged;
}
}
void Update()
{
if (pathCreator != null & (timer % 4 != 0))
{
distanceTravelled += speedOfPlayer * Time.deltaTime;
// Movement along the path
transform.position = pathCreator.path.GetPointAtDistance(distanceTravelled, instructionFinChemin);
// Rotation along the path
transform.rotation = pathCreator.path.GetRotationAtDistance(distanceTravelled, instructionFinChemin);
}
}
// Fonction Coroutine to count time and stop RigidBodyFPSController for 4 secondes
IEnumerator DelayLoadLevel()
{
while (true)
{
yield return new WaitForSeconds(1);
timer = timer + 1;
print("timer = " + timer);
if (pathCreator != null && timer % 4 == 0)
{
Debug.Log("Enter IF timer == 4 secondes");
Spawn();
yield return new WaitForSeconds(4);
}
}
}
//public static void RemoveAt(ref T[] array, int index);
void Spawn()
{
Debug.Log("Enter Spawn function");
if (compteurFixe < itemFixe.Length)
{
Debug.Log("Boucle ITEM FIXE ");
Debug.Log("indexArrayItemFixe " + indexItemFixe);
Debug.Log("indexPositionItemFixe " + indexPositionFixe);
Debug.Log("compteur de la boucle IF " + compteurFixe);
Destroy(Instantiate(itemFixe[indexItemFixe], spawnPoint[indexPositionFixe].position, spawnPoint[indexPositionFixe].rotation), 4);
Debug.Log("Item spawned : " + compteurFixe);
indexItemFixe++;
indexPositionFixe++;
compteurFixe++;
}
else if (compteurMobile < itemMobile.Length && compteurFixe >= itemFixe.Length)
{
Debug.Log("Boucle ITEM MOBILE ");
Debug.Log("indexArrayItemMobile " + indexItemMobile);
Debug.Log("indexPositionItemMobile " + indexPositionMobile);
Debug.Log("compteur de la boucle IF " + compteurMobile);
Destroy(Instantiate(itemMobile[indexItemMobile], spawnPointMobile[indexPositionMobile].position, spawnPointMobile[indexPositionMobile].rotation), 4);
Debug.Log("Item spawned : " + compteurMobile);
indexItemMobile++;
indexPositionMobile++;
compteurMobile++;
}
else if (compteurMixte < itemMixte.Length && compteurFixe >= itemFixe.Length && compteurMobile >= itemMobile.Length)
{
Debug.Log("Boucle ITEM MIXTE");
Debug.Log("indexArrayItemMixte " + indexItemMixte);
Debug.Log("indexPositionItemMixte " + indexPositionMixte);
Debug.Log("compteur de la boucle IF " + compteurMixte);
Destroy(Instantiate(itemMixte[indexItemMixte], spawnPointMixte[indexPositionMixte].position, spawnPointMixte[indexPositionMixte].rotation), 4);
Debug.Log("Item spawned : " + compteurMixte);
indexItemMixte++;
indexPositionMixte++;
compteurMixte++;
}
else { print("No More Item"); }
}
//Function to randomize array's of gameObject
public static void RandomizeArray<T>(T[] array)
{
int size = array.Length; // initialize Size used in the for function
for (int z = 0; z < size; z++)
{
int indexToSwap = Random.Range(z, size);
T swapValue = array[z];
array[z] = array[indexToSwap];
array[indexToSwap] = swapValue;
}
}
// If the path changes during the game, update the distance travelled so that the follower's position on the new path
// is as close as possible to its position on the old path
void OnPathChanged()
{
distanceTravelled = pathCreator.path.GetClosestDistanceAlongPath(transform.position);
}
//End of Script
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.