玩家球通过上下键控制,相机依靠左右键控制,有加力量的东西,玩家球碰到力量吸收后,可以更大力碰撞敌人,当一波球碰掉后,还会生成新一波球。
为玩家和敌人分别加上物理材质
先进入Start开启协程,执行Demo打印002,yield return null的意思是暂停?1帧并且在Update执行完之后才开始执行,所以执行到这时返回start中的StartCoroutine方法,Update会执行一次打印001,因为等待一帧,再打印001,yield结束,打印003。
先进入Update打印001,开启协程(协助主线程,两个同时进行)打印002,yield暂停一帧(等update执行完暂停一帧再次执行,在update之后在lateupdate之前)?,打印003,主线程继续执行打印005,等待暂停一帧则update执行打印001,进入协程打印002再次yield暂停一帧,主线程继续执行打印003此时过去一帧,上一次Demo函数暂停那帧以执行完则打印004,再打印Latepdate里的005,此后一直循环001 002 003? 004 005,每次打印的004都是上次暂停一帧结束后打印的。
在Unity游戏开发引擎中,`Instantiate`是一个用于创建游戏对象副本的函数。当你调用`Instantiate`函数时,它会根据提供的参数创建一个新实例,并将其放置在场景中。
在你提供的代码片段中:
Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
这里有三个参数:
1. `enemyPrefab`:这是一个游戏对象的预制体(Prefab),它通常包含了游戏对象的结构和组件的定义。预制体可以看作是游戏对象的蓝图或模板。
2. `GenerateSpawnPosition()`:这个参数看起来是一个函数调用,它应该返回一个位置向量,这个位置向量指定了新创建的游戏对象应该被放置的位置。在Unity中,你通常需要定义这个函数来确保新实例被放置在合适的位置,比如随机位置或者根据某种规则计算出的位置。
3. `enemyPrefab.transform.rotation`:这个参数是一个四元数,它代表了旋转信息。这里,`enemyPrefab.transform`指的是预制体本身的变换(位置、旋转和缩放),而`rotation`属性则是指预制体的旋转状态。将这个旋转状态传递给`Instantiate`函数意味着新创建的游戏对象将会继承预制体的旋转状态,这样新对象就会以与预制体相同的旋转角度出现在场景中。
总结来说,这行代码的意思是:在指定的位置(由`GenerateSpawnPosition()`函数返回的位置)创建一个`enemyPrefab`预制体的实例,并且这个新创建的实例应该继承预制体的旋转状态。这通常用于在游戏中生成敌人或其他游戏对象,并且确保它们以正确的角度和位置出现。?
using JetBrains.Annotations;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnManager : MonoBehaviour
{
public GameObject enemyPrefab;
public GameObject powerupPrefab;
private float spawnRange = 9;
public int enemyCount;
public int waveNumber = 1;
void Start()
{
SpawnEnemyWave(3);
Instantiate(powerupPrefab, GenerateSpawnPosition(), powerupPrefab.transform.rotation);
}
// Update is called once per frame
void Update()
{
enemyCount = FindObjectsOfType<EnemyController>().Length;
//查找EnemyController类型的对象, FindObjectOfType<EnemyController>()返回EnemyController这个类型的对象,FindObjectsOfType<EnemyController>()找EnemyController类型的数组
if (enemyCount == 0)
{
waveNumber++;
SpawnEnemyWave(waveNumber);
SpawnEnemyWave(1);
Instantiate(powerupPrefab, GenerateSpawnPosition(), powerupPrefab.transform.rotation);
}
}
Vector3 GenerateSpawnPosition()
{
float spawnPosX = Random.Range(-spawnRange, spawnRange);
float spawnPosZ = Random.Range(-spawnRange, spawnRange);
Vector3 randomPos = new Vector3(spawnPosX, 0, spawnPosZ);
return randomPos;
}
void SpawnEnemyWave(int enemiesToSpawn)
{
for(int i = 0; i < enemiesToSpawn; i++)
{
Instantiate(enemyPrefab, GenerateSpawnPosition(), enemyPrefab.transform.rotation);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemyController : MonoBehaviour
{
public float speed;
private Rigidbody enemyRb;
private GameObject player;
void Start()
{
enemyRb = GetComponent<Rigidbody>();
player = GameObject.Find("Player");
}
// Update is called once per frame
void Update()
{
Vector3 lookDirection = (player.transform.position - transform.position).normalized;
enemyRb.AddForce(lookDirection * speed);
//(player.transform.position - transform.position).normalized意思是玩家的位置与敌人的位置之差的向量方向,normalized相当于模【(x*x+y*y+z*z)的平方根】即两个物体之间的相对角度,最后化为一返回一个(x*x+y*y+z*z)的平方根=1的向量x,y,z
//归一化可以防止两球之间距离一直在变,导致速度的改变
if (transform.position.y < -10)
{
Destroy(gameObject);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float speed=5.0f;
private Rigidbody playerRb;
private GameObject focalPoint;
public GameObject powerupIndicator;
public bool hasPowerup=false;
private float powerupStrength=15.0f;
// Start is called before the first frame update
void Start()
{
playerRb = GetComponent<Rigidbody>();
focalPoint = GameObject.Find("Focal Point");
}
// Update is called once per frame
void Update()
{
float forwardInput = Input.GetAxis("Vertical");
playerRb.AddForce(focalPoint.transform.forward * speed * forwardInput);
powerupIndicator.transform.position = transform.position + new Vector3(0, -0.5f, 0);
}
private void OnTriggerEnter(Collider other)//进入此函数的前提是两个物体至少有其中一个勾选了触发器
{
if (other.CompareTag("Powerup")){//加标签更安全,虽然敌人和玩家都没有勾选触发器,即使碰撞也是进不来这个函数的
hasPowerup = true;
Destroy(other.gameObject);//销毁玩家碰撞的钻石
powerupIndicator.gameObject.SetActive(true);
StartCoroutine(PowerupCountdownRoutine());//开启协程
}
}
IEnumerator PowerupCountdownRoutine()//接口
{
yield return new WaitForSeconds(7);//协程做倒计时,yield暂停 执行到此暂停7秒再往后执行
//或者使用最上面定义一个float类型时间,和一个定时器,Update中每次让定时器减去Time.deltaTime(两个帧时间间隔),直到<=0就结束
hasPowerup = false;
powerupIndicator.gameObject.SetActive(false);
}
private void OnCollisionEnter(Collision collision)
{
if (collision.gameObject.CompareTag("Enemy") && hasPowerup)
{
Rigidbody enemyRigidbody = collision.gameObject.GetComponent<Rigidbody>();
Vector3 awayFromPlayer = (collision.gameObject.transform.position - transform.position);
Debug.Log("Collided with " + collision.gameObject.name + " with powerup set to " + hasPowerup);
enemyRigidbody.AddForce(awayFromPlayer * powerupStrength, ForceMode.Impulse); //ForceMode.Impulse顺时爆发
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RotateCamera : MonoBehaviour
{
public float rotationSpeed;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
float horizontalInput = Input.GetAxis("Horizontal");
transform.Rotate(Vector3.up, horizontalInput * rotationSpeed * Time.deltaTime);
}
}
?
?
?