Unity相扑战斗球

本文介绍了Unity游戏中如何通过键盘控制角色移动,利用物理材质设定弹性,以及协程的使用技巧,包括协程启动时机、控制游戏逻辑和Prefab的Instantiate操作。还讨论了预制体中引用对象的问题以及碰撞检测和力量增强的实现。
摘要由CSDN通过智能技术生成

介绍

玩家球通过上下键控制,相机依靠左右键控制,有加力量的东西,玩家球碰到力量吸收后,可以更大力碰撞敌人,当一波球碰掉后,还会生成新一波球。

  • 物理材质的弹力限制数0-1

为玩家和敌人分别加上物理材质

  • 玩家碰撞钻石添加能量,并且钻石消失,这里应该把钻石的触发器勾选上,玩家的触发器不能勾选,因为玩家触发器勾选的话会导致与其他物体碰撞时没有碰撞效果,会穿过去

协程

先进入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都是上次暂停一帧结束后打印的。

  • Instantiate拷贝函数

在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`预制体的实例,并且这个新创建的实例应该继承预制体的旋转状态。这通常用于在游戏中生成敌人或其他游戏对象,并且确保它们以正确的角度和位置出现。 

  • 预制体中引用游戏对象,在与预制体对象相关联的脚本代码中不能public游戏对象然后在场景中拖拽,因为预制体是一个文件,在游戏未运行之前他就存在,而场景中的游戏对象是等游戏运行后才会出现的,所以在未运行时将一个没有的东西拖拽进行赋值是拖拽不进去的。

源码

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);
    }
}

 

 

 

  • 26
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值