我正在编程2D Platformer,但遇到问题/问题/怪异的情况-随便命名。首先,在基本场景中,我有4个Blob(如图所示):
从我的场景中查看:
问题是:当我击中最大的那一击时,它不会受到击退,而上面的较小的那一击则具有击退效果,并且没有伤害。他们每个人都在敌人标签和敌人层上。
有趣的事物-当其中只有一个位于敌人的图层和标记上时,它会获得正确的效果(伤害+击退)。是脚本问题,还是我在Unity中弄乱了东西。
PS。另一个有趣的事情-当我将每个Blob设置在敌人图层和标签上时。然后,我直接(准确地)击中了我上方的那个(带有黄色箭头)。它的行为正确...所以我什至感到困惑。
我的代码(抱歉,由于测试,它被压缩为一个大文件)战斗和移动
[PlayerControls.cs]:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using UnityEngine.Animations;
using UnityEngine.SceneManagement;
public class PlayerControls : MonoBehaviour
{
private float moveHoriz;
public float speed;
public bool grounded;
private float crouch;
public bool crouching;
private Rigidbody2D rb;
bool sliding;
public float slideTimer;
public float maxSlideTime;
public float jumpForce;
public bool facingRight = true;
public bool isDoubleJump = true;
public LayerMask whatIsGround;
public float groundRadius;
public Transform GroundCheck;
public Transform CeilingCheck;
private bool ceiled;
public Transform NearGroundCheck;
private bool isGroundNear;
private int extraJumps;
public int extraJumpValues;
private bool jumping;
private bool attack1;
private bool attack2;
private bool attack3;
private bool airAttack1;
public bool goodOrder1;
public bool goodOrder2;
public bool goodOrder3;
public bool badOrder2;
public bool badOrder3;
public bool combo;
public float comboDuration;
public float comboEndup = 1;
private bool shootBow;
public bool reloadBow = true;
public int reloadTime = 1;
public Transform attackPos;
public float attackRange;
public LayerMask whatIsEnemy;
public int damage;
private EnemyScript enemy;
public Animator animator;
// Use this for initialization
void Start()
{
extraJumps = extraJumpValues;
rb = GetComponent<Rigidbody2D>();
enemy = GameObject.FindGameObjectWithTag("Enemy").GetComponent<EnemyScript>();
}
// Update is called once per frame
void Update()
{
animator.SetFloat("Speed", Mathf.Abs(moveHoriz));
animator.SetBool("Grounded", grounded);
animator.SetFloat("vertSpeed", rb.velocity.y);
animator.SetInteger("isDoubleJump", extraJumps);
animator.SetBool("Crouch", crouching);
animator.SetBool("isSliding", sliding);
animator.SetFloat("stopSliding", slideTimer);
animator.SetBool("isGroundNear", isGroundNear);
animator.SetBool("comboAttack", combo);
animator.SetFloat("comboDuration", comboDuration);
animator.SetBool("reloadBow", reloadBow);
animator.SetFloat("reloadTime", reloadTime);
animator.SetBool("goodOrder1", goodOrder1);
animator.SetBool("goodOrder2", goodOrder2);
animator.SetBool("goodOrder3", goodOrder3);
animator.SetBool("badOrder2", badOrder2);
animator.SetBool("badOrder3", badOrder3);
moveHoriz = Input.GetAxisRaw("Horizontal");
crouch = Input.GetAxisRaw("Crouch");
RangeAttack();
OrderCheck();
Crouch();
if (grounded != true)
{
jumping = true;
sliding = false;
slideTimer = 0;
}
if (grounded == true)
{
jumping = false;
extraJumps = extraJumpValues;
}
if (Input.GetKeyDown(KeyCode.UpArrow) && extraJumps > 0)
{
jumping = true;
rb.velocity = Vector2.up * jumpForce;
extraJumps--;
}
else if (Input.GetKeyDown(KeyCode.UpArrow) && extraJumps == 0 && grounded == true)
{
rb.velocity = Vector2.up * jumpForce;
}
if (Input.GetKeyDown(KeyCode.H))
{
Die();
}
}
void FixedUpdate()
{
grounded = Physics2D.OverlapCircle(GroundCheck.position, groundRadius, whatIsGround);
ceiled = Physics2D.OverlapCircle(CeilingCheck.position, groundRadius, whatIsGround);
isGroundNear = Physics2D.OverlapCircle(NearGroundCheck.position, groundRadius, whatIsGround); ;
rb.velocity = new Vector2(moveHoriz * speed, rb.velocity.y);
Move();
Flip();
Sliding();
Combo();
HandleInput();
HandleAttacks();
DealDmg();
ResetValues();
}
void Move()
{
rb.velocity = new Vector2(moveHoriz * speed, rb.velocity.y);
}
// Flip (or better said Rotate) Character.
void Flip()
{
if ((moveHoriz < 0 && facingRight == true) || (moveHoriz > 0 && facingRight == false))
{
facingRight = !facingRight;
Vector3 theScale = transform.localScale;
theScale.x *= -1;
transform.localScale = theScale;
}
}
void Crouch()
{
if ((crouch != 0 || ceiled == true) && grounded == true)
{
crouching = true;
}
else
{
crouching = false;
}
if (crouching)
{
speed = 10;
}
else
{
speed = 15;
}
}
void Sliding()
{
//If statement to check if player is sliding to maxSlide capacity
if (Input.GetButtonDown("Crouch") && speed > 0)
{
slideTimer = 0f;
sliding = true;
if (slideTimer >= maxSlideTime && sliding == true || moveHoriz == 0)
{
sliding = false;
animator.SetBool("isSliding", false);
crouching = true;
animator.SetBool("Crouch", false);
}
}
if (slideTimer < maxSlideTime && moveHoriz == 0 && crouch > 0)
{
sliding = false;
animator.SetBool("isSliding", false);
animator.SetBool("Crouch", true);
crouching = true;
}
if (sliding)
{
speed = 25;
slideTimer += Time.deltaTime;
if (slideTimer >= maxSlideTime || jumping == true)
{
sliding = false;
animator.SetBool("isSliding", false);
speed = 15;
}
if (facingRight == true)
{
rb.velocity = Vector2.right * speed;
}
else if (facingRight != true)
{
rb.velocity = Vector2.left * speed;
}
}
}
void HandleAttacks()
{
if (attack1 == true)
{
goodOrder1 = true;
goodOrder2 = false;
goodOrder3 = false;
}
if (attack2 == true)
{
goodOrder1 = false;
goodOrder2 = true;
goodOrder3 = false;
}
if (attack3 == true)
{
goodOrder1 = false;
goodOrder2 = false;
goodOrder3 = true;
}
if (airAttack1)
{
animator.SetTrigger("airAttack1");
attackRange = 1;
}
}
private void HandleInput()
{
if (Input.GetButtonDown("Attack1"))
{
attack1 = true;
}
else if (Input.GetButtonUp("Attack1"))
{
attack1 = false;
}
if (Input.GetButtonDown("Attack2"))
{
attack2 = true;
}
else if (Input.GetButtonUp("Attack2"))
{
attack2 = false;
}
if (Input.GetButtonDown("Attack3"))
{
attack3 = true;
}
else if (Input.GetButtonUp("Attack3"))
{
attack3 = false;
}
if (grounded == false && (Input.GetButtonDown("Attack1") || Input.GetButtonDown("Attack2") || Input.GetButtonDown("Attack3")))
{
airAttack1 = true;
attack1 = false;
}
if (airAttack1 == true && grounded == true)
{
airAttack1 = false;
}
}
void OrderCheck()
{
// First sequence attack
if (grounded == true && attack1 == true && comboDuration > 0)
{
goodOrder1 = true;
}
else if (goodOrder1 != true && grounded == true && attack2 == true && comboDuration <= 0)
{
badOrder2 = true;
}
// Second sequence attack
if (grounded == true && attack2 == true && comboDuration > 0)
{
goodOrder2 = true;
}
else if (goodOrder1 != true && grounded == true && attack3 == true && comboDuration <= 0)
{
badOrder3 = true;
}
// Third sequence attack
if (grounded == true && attack3 == true && comboDuration > 0)
{
goodOrder3 = true;
}
else if (goodOrder2 != true && grounded == true && goodOrder1 != true && comboDuration > 0)
{
badOrder3 = true;
}
// Clear if badOrder's achived
if (badOrder2 == true || badOrder3 == true)
{
goodOrder1 = false;
goodOrder2 = false;
goodOrder3 = false;
}
}
void Combo()
{
if (attack1 == true)
{
comboDuration = comboEndup;
}
/*if ((goodOrder1 == true || goodOrder2 == true || goodOrder3 == true) || (badOrder2 == true || badOrder3 == true))
{
comboDuration = comboEndup;
}*/
// comboEndup = 1; - reminder
if (comboDuration > 0)
{
comboDuration -= Time.deltaTime;
combo = true;
}
if (comboDuration <= 0 || (badOrder2 == true || badOrder3 == true))
{
comboDuration = 0;
combo = false;
goodOrder1 = false;
goodOrder2 = false;
goodOrder3 = false;
badOrder2 = false;
badOrder3 = false;
}
}
void ResetValues()
{
if (badOrder2 == true || badOrder3 == true)
{
badOrder2 = false;
badOrder3 = false;
}
airAttack1 = false;
if (gameObject.GetComponent<PlayerControls>().grounded == true && airAttack1 == true)
{
airAttack1 = false;
}
}
private void RangeAttack()
{
if (grounded == true && Input.GetButtonDown("Ranged"))
{
animator.SetTrigger("shootBow");
reloadBow = false;
attack1 = false;
attack2 = false;
attack3 = false;
}
}
void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(attackPos.position, attackRange);
}
public void DealDmg()
{
if (attackPos.gameObject.activeSelf == true)
{
Collider2D[] enemiesToDamage = Physics2D.OverlapCircleAll(attackPos.position, attackRange, whatIsEnemy);
for (int i = 0; i < enemiesToDamage.Length; i++)
{
enemiesToDamage[i].GetComponent<EnemyScript>().TakeDmg(damage);
if (facingRight == true)
{
gameObject.GetComponent<EnemyScript>().EnemyRB.AddForce(transform.up * 500 + transform.right * 500);
}
else if (facingRight == false)
{
gameObject.GetComponent<EnemyScript>().EnemyRB.AddForce(transform.up * 500 + (transform.right * 500) * -1);
}
attackPos.gameObject.SetActive(false);
}
}
}
void Die()
{
SceneManager.LoadScene(0);
}
}
敌人运动[EnemyScript.cs]:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class EnemyScript : MonoBehaviour {
public float speed;
public float distance;
public int health;
public bool movingRight = true;
public Transform groundDetection;
public Rigidbody2D EnemyRB;
public bool trap;
public LayerMask TrapLayer;
public Transform ColideDetector;
public float detectorRadius;
public BoxCollider2D CheckHeadBounce;
// Use this for initialization
void Start ()
{
EnemyRB = gameObject.GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update ()
{
trap = Physics2D.OverlapCircle(ColideDetector.position, detectorRadius, TrapLayer);
if (health <= 0)
{
Destroy(gameObject);
}
transform.Translate(Vector2.right * speed * Time.deltaTime );
RaycastHit2D groundInfo = Physics2D.Raycast(groundDetection.position, Vector2.down, distance);
if (groundInfo.collider == false || trap == true)
{
if(movingRight == true)
{
transform.eulerAngles = new Vector3(0, -180, 0);
movingRight = false;
}
else
{
transform.eulerAngles = new Vector3(0, 0, 0);
movingRight = true;
}
}
}
public void HeadBounce()
{
}
public void TakeDmg(int damage)
{
health -= damage;
Debug.Log("damage TAKEN!");
}
}
It's a gif to show what is going on
答案 0 :(得分:1)
您没有在EnemyScript
内使用DealDmg
的正确引用。在循环中,您首先呼叫TakDmg
上发现的敌人OverlapCircleAll
,然后呼叫AddForce
上的gameObject.GetComponent<EnemyScript>().EnemyRB
。
在这种情况下,gameObject
指的是运行脚本附加到的GameObject(此处为PlayerControl.cs
)。您需要在碰撞数组enemisToDamage
内的游戏对象的刚体上施加力,就像对TakeDmg
所做的一样。
这是一个可能的解决方案。
public void DealDmg()
{
if (attackPos.gameObject.activeSelf == true)
{
Collider2D[] enemiesToDamage = Physics2D.OverlapCircleAll(attackPos.position, attackRange, whatIsEnemy);
for (int i = 0; i < enemiesToDamage.Length; i++)
{
EnemyScript enemyScript = enemiesToDamage[i].GetComponent<EnemyScript>();
enemyScript.TakeDmg(damage);
if (facingRight == true)
{
enemyScript.GetComponent<RigidBody>().AddForce(transform.up * 500 + transform.right * 500);
}
else if (facingRight == false)
{
enemyScript.GetComponent<RigidBody>().AddForce(transform.up * 500 + (transform.right * 500) * -1);
}
attackPos.gameObject.SetActive(false);
}
}
}