Управление под платформер и top-down shooter [2D]

Ранее мы публиковали скрипт, который имел два режима работы, как для управления под платформер, так и для топ-даун шутера. Однако, удобство его использования оказалось достаточно сомнительным, особенно если нужно только один из режимов для проекта, в этом случаи получалось много лишнего кода, что мешало разобраться в нем. Поэтому было принято решение произвести обновление, вместо одного скрипта, теперь их два, каждый заточен под свои задачи, кроме того сам код несколько улучшен, всё лишние убрано. Как и прежде всё работает исключительно с 2D физикой и камерой в режиме ортогональной проекции.

Платформер

Скрипт Character2DPlatformer:

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody2D))]

public class Character2DPlatformer : MonoBehaviour {

	public float speed = 1.5f; // скорость движения
	public float acceleration = 100; // ускорение
	public float jumpForce = 5; // сила прыжка
	public float jumpDistance = 0.75f; // расстояние от центра объекта, до поверхности (определяется вручную в зависимости от размеров спрайта)
	public bool facingRight = true; // в какую сторону смотрит персонаж на старте?
	public KeyCode jumpButton = KeyCode.Space; // клавиша для прыжка

	private Vector3 direction;
	private int layerMask;
	private Rigidbody2D body;
	
	void Start () 
	{
		body = GetComponent<Rigidbody2D>();
		body.freezeRotation = true;
		layerMask = 1 << gameObject.layer | 1 << 2;
		layerMask = ~layerMask;
	}

	bool GetJump() // проверяем, есть ли коллайдер под ногами
	{
		bool result = false;

		RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector3.down, jumpDistance, layerMask);
		if(hit.collider)
		{
			result = true;
		}

		return result;
	}
	
	void FixedUpdate()
	{
		body.AddForce(direction * body.mass * speed * acceleration);
		
		if(Mathf.Abs(body.velocity.x) > speed)
		{
			body.velocity = new Vector2(Mathf.Sign(body.velocity.x) * speed, body.velocity.y);
		}
	}
	
	void Flip() // отражение по горизонтали
	{
		facingRight = !facingRight;
		Vector3 theScale = transform.localScale;
		theScale.x *= -1;
		transform.localScale = theScale;
	}
	
	void Update () 
	{	
		Debug.DrawRay(transform.position, Vector3.down * jumpDistance, Color.red); // подсветка, для визуальной настройки jumpDistance

		if(Input.GetKeyDown(jumpButton) && GetJump())
		{
			body.velocity = new Vector2(0, jumpForce);
		}

		float h = Input.GetAxis("Horizontal");
		
		direction = new Vector2(h, 0); 
		
		if(h > 0 && !facingRight) Flip(); else if(h < 0 && facingRight) Flip();
	}
}

Чтобы всё работало как надо, персонажу нужно назначить отдельный слой, например с именем Player. Это нужно для того, чтобы работал рейкаст в скрипте, который определяет возможность прыжка и в тоже время для того, чтобы любой другой рейкаст, мог взаимодействовать и игроком. Дополнительно, стоит добавить физический материал Physics Material 2D и прицепить его на коллайдер персонажа, в настройках материала, параметр Friction ставим, например на 100, то есть, чтоб моделька не скользила как утюг на льду.

Top-Down Shooter

Скрипт Character2DTopDown:

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody2D))]

public class Character2DTopDown : MonoBehaviour {

	public float speed = 1.5f;
	public float acceleration = 100;

	private Vector3 direction;
	private Rigidbody2D body;

	void Start () 
	{
		body = GetComponent<Rigidbody2D>();
		body.freezeRotation = true;
		body.gravityScale = 0;
	}

	void FixedUpdate()
	{
		body.AddForce(direction * body.mass * speed * acceleration);
		
		if(Mathf.Abs(body.velocity.x) > speed)
		{
			body.velocity = new Vector2(Mathf.Sign(body.velocity.x) * speed, body.velocity.y);
		}
		
		if(Mathf.Abs(body.velocity.y) > speed)
		{
			body.velocity = new Vector2(body.velocity.x, Mathf.Sign(body.velocity.y) * speed);
		}
	}

	void LookAtCursor()
	{
		Vector3 lookPos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, Camera.main.transform.position.z));
		lookPos = lookPos - transform.position;
		float angle  = Mathf.Atan2(lookPos.y, lookPos.x) * Mathf.Rad2Deg;
		transform.rotation = Quaternion.AngleAxis(angle, Vector3.forward);
	}

	void Update () 
	{
		direction = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));

		LookAtCursor();
	}
}

Здесь особых хитростей не нужно, всё достаточно просто. У камеры должен быть установлен стандартный тег MainCamera. А спрайт персонажа необходимо развернуть так, чтобы его лицо было ориентировано по направлению оси Х:

Управление под платформер и top-down shooter [2D]

Скачать пример проекта:

Внимание! Посетители, находящиеся в группе Гости, не могут скачивать файлы.

Комментариев 4

Офлайн
chudaky 15 июня 2016
что значит
body.freezeRotation = true;
(заморозить поворот тела ?)
просто в версии 4.5 нету такого свойства, только тут застрял код
Офлайн
Light 15 июня 2016
Цитата: chudaky
(заморозить поворот тела ?)

Да, просто заменить строку на аналогичную. Что-то вроде этого:

body.fixedAngle = true;
Офлайн
SleepyAsh 24 июля 2018
Light,
День добрый. Возникла небольшая проблема. Когда персонаж приземляется на угол коллайдера не самым днищем так сказать. И если при этом нажимать движение вперед то он просто застревает и не может подняться. Как это можно исправить?
Офлайн
Light 24 июля 2018
SleepyAsh, для этого есть в разделе физики Platform Effector 2D.
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Дешевый хостинг
  • Яндекс.Метрика