Unity 2d 角色用UI 按钮移动和跳转到特定位置
Unity 2d Character moves and jumps to specific positions with UI buttons
在一个简单的 2d 项目中,我的播放器可以在 x 上向右和向左移动,还可以使用其他两个按钮在高度上向右和向左跳。问题是,玩家不应该自由移动。通过按下其中一个按钮,玩家应该只转到下一个特定点,这样玩家总是会停在 x 轴上的六个不同位置(而在 y 轴上他是自由的,并且与他当前站在的平台一样高)。为了能够逼真地跳跃,玩家必须有重力和碰撞器才能降落在平台上(并水平移动单个平台)。
感谢@TEEBQNE 在评论中链接的教程,我终于可以使用 Unitys Rigidbody2D 和以下脚本实现这一点。问题是重力现在表现得很奇怪。玩家只能非常缓慢地向下移动,并在此过程中将游戏对象推到其下方。玩家有一个重力标度为 2 的 Dynamic Rigidbody2D 和一个 2d 胶囊对撞机。这是脚本问题还是玩家检查器中的组件问题?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movePlayer : MonoBehaviour
{
public GameObject posChecker1;
public GameObject posChecker2;
public GameObject posChecker3;
public GameObject posChecker4;
public GameObject posChecker5;
public GameObject posChecker6;
public bool go; //Player is allowed to move
public bool grounded; //Player is allowed to jump
public string moveDirection;
public float horizVel = 0; //Movement along x
public float verticVel = 0; //Jump
public int laneNum = 3; //Player starts on lane 3!!
public bool rightButtonMove = false;//
public bool leftButtonMove = false;//
public bool rightButtonJump = false;//
public bool leftButtonJump = false;//
//Animation
private SpriteRenderer spriteRenderer;
private Animator animator;
private void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
animator = GetComponent<Animator>();
}
// Start is called before the first frame update
void Start()
{
posChecker1.SetActive(true);//GameObject.Find("PositionChecker1").SetActive(true);
posChecker2.SetActive(true);
posChecker3.SetActive(true); //Player start on lane 3!!
posChecker4.SetActive(true);
posChecker5.SetActive(true);
posChecker6.SetActive(true);
laneNum = 3;
go = true;
}
// Update is called once per frame
void Update()
{
//Raycast
int playerMask = LayerMask.GetMask("PositionChecker");// !!!
Debug.DrawRay(transform.position, transform.TransformDirection(Vector2.up) * 50f, Color.green);
RaycastHit2D hitCheck = Physics2D.Raycast(transform.position, transform.TransformDirection(Vector2.up), 50f, playerMask);
//Only the checker objects in the rows next to the player are active
if (laneNum == 1)
{
posChecker1.SetActive(false);
posChecker2.SetActive(true);
}
else if (laneNum == 2)
{
posChecker1.SetActive(true);
posChecker2.SetActive(false);
posChecker3.SetActive(true);
}
else if (laneNum == 3)
{
posChecker2.SetActive(true);
posChecker3.SetActive(false);
posChecker4.SetActive(true);
}
else if (laneNum == 4)
{
posChecker3.SetActive(true);
posChecker4.SetActive(false);
posChecker5.SetActive(true);
}
else if (laneNum == 5)
{
posChecker4.SetActive(true);
posChecker5.SetActive(false);
posChecker6.SetActive(true);
}
else if (laneNum == 6)
{
posChecker5.SetActive(true);
posChecker6.SetActive(false);
}
//Movement
GetComponent<Rigidbody2D>().velocity = new Vector3(horizVel, verticVel, 0);
//Raycast
if (hitCheck)
{
if (moveDirection == "l" && horizVel != 0)
{
laneNum -= 1;
}
if (moveDirection == "r" && horizVel != 0)
{
laneNum += 1;
}
go = true;
horizVel = 0;
verticVel = 0;
grounded = true;
}
if (horizVel == 0)
moveDirection = "";
//Animation
bool flipSprite = (spriteRenderer.flipX ? (horizVel > 0.01f) : (horizVel < 0.01f));
if (flipSprite)
{
spriteRenderer.flipX = !spriteRenderer.flipX;
}
animator.SetBool("grounded", grounded); // -->Jump
animator.SetFloat("velocityX", Mathf.Abs(horizVel));
}
//Button Input
public void RightButton() //
{
if (laneNum < 6 && go)
{
moveDirection = "r";
go = false;
horizVel = 4;
}
}
public void LeftButton()//
{
if (laneNum > 1 && go)
{
moveDirection = "l";
go = false;
horizVel = -4;
}
}
public void RightJump()//
{
if (laneNum < 6 && grounded && go)
{
moveDirection = "r";
horizVel = 4;
verticVel = 7;
go = false;
grounded = false;
}
}
public void LeftJump()//
{
if (laneNum > 1 && grounded && go)
{
moveDirection = "l";
horizVel = -4;
verticVel = 7;
go = false;
grounded = false;
}
}
}
很高兴我能够以某种方式提供帮助,并且您已经解决了您的问题!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movePlayer : MonoBehaviour
{
//Player Position x
public GameObject posChecker1;
public GameObject posChecker2;
public GameObject posChecker3;
public GameObject posChecker4;
public GameObject posChecker5;
public GameObject posChecker6;
public int laneNum = 3; //Player starts on lane 3!!
//Player Position y
public float yPos1;
public float yPos2;
public Transform player;
//Movement Variables
public bool go; //Player is allowed to move
public bool grounded; //Player is allowed to jump
public string moveDirection;
public float horizVel = 0; //Movement along x
public float verticVel = 0; //Jump
//Animation
private SpriteRenderer spriteRenderer;
private Animator animator;
private void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
animator = GetComponent<Animator>();
}
// Start is called before the first frame update
void Start()
{
posChecker1.SetActive(true);//GameObject.Find("PositionChecker1").SetActive(true);
posChecker2.SetActive(true);
posChecker3.SetActive(true); //Player start on lane 3!!
posChecker4.SetActive(true);
posChecker5.SetActive(true);
posChecker6.SetActive(true);
laneNum = 3;
go = true;
}
// Update is called once per frame
void Update()
{
//Raycast
int playerMask = LayerMask.GetMask("PositionChecker");// !!!
Debug.DrawRay(transform.position, transform.TransformDirection(Vector2.up) * 50f, Color.green);
RaycastHit2D hitCheck = Physics2D.Raycast(transform.position, transform.TransformDirection(Vector2.up), 50f, playerMask);
//Only the checker objects in the rows next to the player are active
if (laneNum == 1)
{
posChecker1.SetActive(false);
posChecker2.SetActive(true);
}
else if (laneNum == 2)
{
posChecker1.SetActive(true);
posChecker2.SetActive(false);
posChecker3.SetActive(true);
}
else if (laneNum == 3)
{
posChecker2.SetActive(true);
posChecker3.SetActive(false);
posChecker4.SetActive(true);
}
else if (laneNum == 4)
{
posChecker3.SetActive(true);
posChecker4.SetActive(false);
posChecker5.SetActive(true);
}
else if (laneNum == 5)
{
posChecker4.SetActive(true);
posChecker5.SetActive(false);
posChecker6.SetActive(true);
}
else if (laneNum == 6)
{
posChecker5.SetActive(true);
posChecker6.SetActive(false);
}
//Movement
if (grounded)
{
verticVel = GetComponent<Rigidbody2D>().velocity.y;
}
GetComponent<Rigidbody2D>().velocity = new Vector3(horizVel, /*GetComponent<Rigidbody2D>().velocity.y*/verticVel, 0);
//Jump
yPos2 = player.transform.position.y;
if ((yPos2 - 2) >= yPos1 && !grounded)
{
if (moveDirection == "l")
horizVel = -4;
if (moveDirection == "r")
horizVel = 4;
verticVel = verticVel * 0.95f;
}
//Raycast
if (hitCheck)
{
if (moveDirection == "l" && horizVel != 0)
{
laneNum -= 1;
}
if (moveDirection == "r" && horizVel != 0)
{
laneNum += 1;
}
go = true;
horizVel = 0;
verticVel = 0;
grounded = true;
}
if (horizVel == 0 && grounded)
moveDirection = "";
//Animation
bool flipSprite = (spriteRenderer.flipX ? (horizVel > 0.01f) : (horizVel < 0.01f));
if (flipSprite)
{
spriteRenderer.flipX = !spriteRenderer.flipX;
}
animator.SetBool("grounded", grounded); // -->Jump
animator.SetFloat("velocityX", Mathf.Abs(horizVel));
}
//Button Input
public void RightButton() //
{
if (laneNum < 6 && go)
{
moveDirection = "r";
go = false;
horizVel = 4;
}
}
public void LeftButton()//
{
if (laneNum > 1 && go)
{
moveDirection = "l";
go = false;
horizVel = -4;
}
}
public void RightJump()//
{
if (laneNum < 6 && grounded && go)
{
moveDirection = "r";
verticVel = 5;
go = false;
grounded = false;
//
yPos1 = player.transform.position.y;
Debug.Log(yPos1);
//
}
}
public void LeftJump()//
{
if (laneNum > 1 && grounded && go)
{
moveDirection = "l";
verticVel = 5;
go = false;
grounded = false;
//
yPos1 = player.transform.position.y;
Debug.Log(yPos1);
//
}
}
}
在一个简单的 2d 项目中,我的播放器可以在 x 上向右和向左移动,还可以使用其他两个按钮在高度上向右和向左跳。问题是,玩家不应该自由移动。通过按下其中一个按钮,玩家应该只转到下一个特定点,这样玩家总是会停在 x 轴上的六个不同位置(而在 y 轴上他是自由的,并且与他当前站在的平台一样高)。为了能够逼真地跳跃,玩家必须有重力和碰撞器才能降落在平台上(并水平移动单个平台)。 感谢@TEEBQNE 在评论中链接的教程,我终于可以使用 Unitys Rigidbody2D 和以下脚本实现这一点。问题是重力现在表现得很奇怪。玩家只能非常缓慢地向下移动,并在此过程中将游戏对象推到其下方。玩家有一个重力标度为 2 的 Dynamic Rigidbody2D 和一个 2d 胶囊对撞机。这是脚本问题还是玩家检查器中的组件问题?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movePlayer : MonoBehaviour
{
public GameObject posChecker1;
public GameObject posChecker2;
public GameObject posChecker3;
public GameObject posChecker4;
public GameObject posChecker5;
public GameObject posChecker6;
public bool go; //Player is allowed to move
public bool grounded; //Player is allowed to jump
public string moveDirection;
public float horizVel = 0; //Movement along x
public float verticVel = 0; //Jump
public int laneNum = 3; //Player starts on lane 3!!
public bool rightButtonMove = false;//
public bool leftButtonMove = false;//
public bool rightButtonJump = false;//
public bool leftButtonJump = false;//
//Animation
private SpriteRenderer spriteRenderer;
private Animator animator;
private void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
animator = GetComponent<Animator>();
}
// Start is called before the first frame update
void Start()
{
posChecker1.SetActive(true);//GameObject.Find("PositionChecker1").SetActive(true);
posChecker2.SetActive(true);
posChecker3.SetActive(true); //Player start on lane 3!!
posChecker4.SetActive(true);
posChecker5.SetActive(true);
posChecker6.SetActive(true);
laneNum = 3;
go = true;
}
// Update is called once per frame
void Update()
{
//Raycast
int playerMask = LayerMask.GetMask("PositionChecker");// !!!
Debug.DrawRay(transform.position, transform.TransformDirection(Vector2.up) * 50f, Color.green);
RaycastHit2D hitCheck = Physics2D.Raycast(transform.position, transform.TransformDirection(Vector2.up), 50f, playerMask);
//Only the checker objects in the rows next to the player are active
if (laneNum == 1)
{
posChecker1.SetActive(false);
posChecker2.SetActive(true);
}
else if (laneNum == 2)
{
posChecker1.SetActive(true);
posChecker2.SetActive(false);
posChecker3.SetActive(true);
}
else if (laneNum == 3)
{
posChecker2.SetActive(true);
posChecker3.SetActive(false);
posChecker4.SetActive(true);
}
else if (laneNum == 4)
{
posChecker3.SetActive(true);
posChecker4.SetActive(false);
posChecker5.SetActive(true);
}
else if (laneNum == 5)
{
posChecker4.SetActive(true);
posChecker5.SetActive(false);
posChecker6.SetActive(true);
}
else if (laneNum == 6)
{
posChecker5.SetActive(true);
posChecker6.SetActive(false);
}
//Movement
GetComponent<Rigidbody2D>().velocity = new Vector3(horizVel, verticVel, 0);
//Raycast
if (hitCheck)
{
if (moveDirection == "l" && horizVel != 0)
{
laneNum -= 1;
}
if (moveDirection == "r" && horizVel != 0)
{
laneNum += 1;
}
go = true;
horizVel = 0;
verticVel = 0;
grounded = true;
}
if (horizVel == 0)
moveDirection = "";
//Animation
bool flipSprite = (spriteRenderer.flipX ? (horizVel > 0.01f) : (horizVel < 0.01f));
if (flipSprite)
{
spriteRenderer.flipX = !spriteRenderer.flipX;
}
animator.SetBool("grounded", grounded); // -->Jump
animator.SetFloat("velocityX", Mathf.Abs(horizVel));
}
//Button Input
public void RightButton() //
{
if (laneNum < 6 && go)
{
moveDirection = "r";
go = false;
horizVel = 4;
}
}
public void LeftButton()//
{
if (laneNum > 1 && go)
{
moveDirection = "l";
go = false;
horizVel = -4;
}
}
public void RightJump()//
{
if (laneNum < 6 && grounded && go)
{
moveDirection = "r";
horizVel = 4;
verticVel = 7;
go = false;
grounded = false;
}
}
public void LeftJump()//
{
if (laneNum > 1 && grounded && go)
{
moveDirection = "l";
horizVel = -4;
verticVel = 7;
go = false;
grounded = false;
}
}
}
很高兴我能够以某种方式提供帮助,并且您已经解决了您的问题!
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class movePlayer : MonoBehaviour
{
//Player Position x
public GameObject posChecker1;
public GameObject posChecker2;
public GameObject posChecker3;
public GameObject posChecker4;
public GameObject posChecker5;
public GameObject posChecker6;
public int laneNum = 3; //Player starts on lane 3!!
//Player Position y
public float yPos1;
public float yPos2;
public Transform player;
//Movement Variables
public bool go; //Player is allowed to move
public bool grounded; //Player is allowed to jump
public string moveDirection;
public float horizVel = 0; //Movement along x
public float verticVel = 0; //Jump
//Animation
private SpriteRenderer spriteRenderer;
private Animator animator;
private void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
animator = GetComponent<Animator>();
}
// Start is called before the first frame update
void Start()
{
posChecker1.SetActive(true);//GameObject.Find("PositionChecker1").SetActive(true);
posChecker2.SetActive(true);
posChecker3.SetActive(true); //Player start on lane 3!!
posChecker4.SetActive(true);
posChecker5.SetActive(true);
posChecker6.SetActive(true);
laneNum = 3;
go = true;
}
// Update is called once per frame
void Update()
{
//Raycast
int playerMask = LayerMask.GetMask("PositionChecker");// !!!
Debug.DrawRay(transform.position, transform.TransformDirection(Vector2.up) * 50f, Color.green);
RaycastHit2D hitCheck = Physics2D.Raycast(transform.position, transform.TransformDirection(Vector2.up), 50f, playerMask);
//Only the checker objects in the rows next to the player are active
if (laneNum == 1)
{
posChecker1.SetActive(false);
posChecker2.SetActive(true);
}
else if (laneNum == 2)
{
posChecker1.SetActive(true);
posChecker2.SetActive(false);
posChecker3.SetActive(true);
}
else if (laneNum == 3)
{
posChecker2.SetActive(true);
posChecker3.SetActive(false);
posChecker4.SetActive(true);
}
else if (laneNum == 4)
{
posChecker3.SetActive(true);
posChecker4.SetActive(false);
posChecker5.SetActive(true);
}
else if (laneNum == 5)
{
posChecker4.SetActive(true);
posChecker5.SetActive(false);
posChecker6.SetActive(true);
}
else if (laneNum == 6)
{
posChecker5.SetActive(true);
posChecker6.SetActive(false);
}
//Movement
if (grounded)
{
verticVel = GetComponent<Rigidbody2D>().velocity.y;
}
GetComponent<Rigidbody2D>().velocity = new Vector3(horizVel, /*GetComponent<Rigidbody2D>().velocity.y*/verticVel, 0);
//Jump
yPos2 = player.transform.position.y;
if ((yPos2 - 2) >= yPos1 && !grounded)
{
if (moveDirection == "l")
horizVel = -4;
if (moveDirection == "r")
horizVel = 4;
verticVel = verticVel * 0.95f;
}
//Raycast
if (hitCheck)
{
if (moveDirection == "l" && horizVel != 0)
{
laneNum -= 1;
}
if (moveDirection == "r" && horizVel != 0)
{
laneNum += 1;
}
go = true;
horizVel = 0;
verticVel = 0;
grounded = true;
}
if (horizVel == 0 && grounded)
moveDirection = "";
//Animation
bool flipSprite = (spriteRenderer.flipX ? (horizVel > 0.01f) : (horizVel < 0.01f));
if (flipSprite)
{
spriteRenderer.flipX = !spriteRenderer.flipX;
}
animator.SetBool("grounded", grounded); // -->Jump
animator.SetFloat("velocityX", Mathf.Abs(horizVel));
}
//Button Input
public void RightButton() //
{
if (laneNum < 6 && go)
{
moveDirection = "r";
go = false;
horizVel = 4;
}
}
public void LeftButton()//
{
if (laneNum > 1 && go)
{
moveDirection = "l";
go = false;
horizVel = -4;
}
}
public void RightJump()//
{
if (laneNum < 6 && grounded && go)
{
moveDirection = "r";
verticVel = 5;
go = false;
grounded = false;
//
yPos1 = player.transform.position.y;
Debug.Log(yPos1);
//
}
}
public void LeftJump()//
{
if (laneNum > 1 && grounded && go)
{
moveDirection = "l";
verticVel = 5;
go = false;
grounded = false;
//
yPos1 = player.transform.position.y;
Debug.Log(yPos1);
//
}
}
}