[英]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.