Пишем игру «Отражение» или «Reflection», как-то так

Значит суть в чём, в игре мы управляем неким шариком и задача в том, чтобы пробираться выше, прыгая с блока на блок. Вроде просто, но штука в том, что экран разделен на две части, блоки слева – это отражение блоков справа, и наоборот. Шарик с другой стороны, тоже отражение. Часть блоков на каждой из сторон отсутствует, но там где нет блока с слева, есть справа. Поэтому приходится ориентироваться на отражение, как шарика, так и блока. Кроме того, периодически управление переключается слева на право и наоборот, время выбирается рандомно. На самом деле идея не нова, тем не менее, у нее неплохой потенциал. Например, можно сделать движущиеся платформы, ловушки, бонусы и т.п.


Как видно на скриншоте это 2D проект. Еще понадобится пара спрайтов, квадрат и круг, белого цвета, перекрашивать будем позже. Так как игра двухмерная, не забываем что коллайдеры и риджитбоди, тоже в 2D физике берем. Итак, вешаем коллайдер на блок и например, с правой стороны экрана выстраиваем карту для героя, сразу надо делать так чтобы прохождение по одной стороне было возможно. У всех блоков должен быть общий родитель и на него мы вешаем вспомогательный скрипт MapReflection:


using UnityEngine;
using System.Collections;

public class MapReflection : MonoBehaviour {

	private GameObject[] obj;

	void Start () 
	{
		obj = new GameObject[transform.childCount];
		for(int i = 0; i < obj.Length; i++)
		{
			obj[i] = Instantiate(transform.GetChild(i).gameObject, Vector3.zero, Quaternion.identity) as GameObject;
			obj[i].transform.parent = transform;
			obj[i].name = "Reflection_" + i;
			obj[i].GetComponent<SpriteRenderer>().color = Color.black;
			obj[i].transform.position = new Vector3(transform.GetChild(i).position.x * -1, transform.GetChild(i).position.y, transform.GetChild(i).position.z);
			obj[i].transform.rotation = Quaternion.Euler(new Vector3(transform.GetChild(i).eulerAngles.x, transform.GetChild(i).eulerAngles.y, transform.GetChild(i).eulerAngles.z * -1));
		}
	}
}

Смысл в том, что он берет все дочерние объекты и делает отражение их по горизонтали и вращение тоже. Нужно запустить сцену, затем перетащить родителя в папку, чтобы сделать временный префаб. Затем, удаляем оригинал и на основе префаба продолжаем доделывать карту, не забыв убрать скрипт.


Активная сторона только одна, определитесь которая. Далее, на активной стороне нужные блоки надо сделать прозрачными, а на другой стороне их можно удалить или тоже сделать невидимыми.


Из спрайта круга, делаем префаб нашего героя с 2D коллайдером и вешаем на него скрипт Player2DControl:

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody2D))]

public class Player2DControl : MonoBehaviour {

	public float speed = 80;
	public float addForce = 8;
	public KeyCode leftButton = KeyCode.A;
	public KeyCode rightButton = KeyCode.D;
	public KeyCode upButton = KeyCode.W;
	public KeyCode downButton = KeyCode.S;
	public KeyCode addForceButton = KeyCode.Space;
	private Vector3 direction;
	private float horizontal;
	private Rigidbody2D body;
	private bool jump;
	
	void Start () 
	{
		body = GetComponent<Rigidbody2D>();
		body.freezeRotation = true;
	}
	
	void OnCollisionStay2D(Collision2D coll) 
	{
		body.drag = 10;
		jump = true;
	}
	
	void OnCollisionExit2D(Collision2D coll) 
	{
		body.drag = 0;
		jump = false;
	}
	
	void FixedUpdate()
	{
		body.AddForce(direction * body.mass * speed);
		
		if(Mathf.Abs(body.velocity.x) > speed/100f)
		{
			body.velocity = new Vector2(Mathf.Sign(body.velocity.x) * speed/100f, body.velocity.y);
		}
	}
	
	void Update ()
	{
		if(Input.GetKeyDown(addForceButton) && jump)
		{
			body.velocity = new Vector2(0, addForce);
		}

		GameControl.playerVelocity = body.velocity.y;
		
		if(Input.GetKey(leftButton)) if(!GameControl.reflection) horizontal = -1; else horizontal = 1;
		else if(Input.GetKey(rightButton)) if(!GameControl.reflection) horizontal = 1; else horizontal = -1; else horizontal = 0;

		direction = new Vector2(horizontal, 0); 
	}
}

Простенький скрипт управления.

Итак, теперь надо чтобы в начале игры, игрок появлялся в нужном месте и его отражение тоже. Создаем пустой объект с любым именем и устанавливаем его на точку, где должен спауниться игрок. Цепляем на объект скрипт GameControl:

using UnityEngine;
using System.Collections;

public class GameControl : MonoBehaviour {

	public static float playerVelocity;
	public static bool reflection;

	public GameObject playerPrefab;
	public Color playerColor = Color.white;
	private GameObject player;
	private GameObject playerReflection;

	void Start () 
	{
		reflection = false;
		StartCoroutine (WaitReflection());
		Reset();
	}

	void Reset()
	{
		Destroy(playerReflection);
		player = Instantiate(playerPrefab, transform.position, Quaternion.identity) as GameObject;
		player.name = "Player";
		playerReflection = Instantiate(player, new Vector3(player.transform.position.x * -1, player.transform.position.y, player.transform.position.z), Quaternion.identity) as GameObject;
		Destroy(playerReflection.GetComponent<Player2DControl>());
		Destroy(playerReflection.GetComponent<Rigidbody2D>());
		playerReflection.GetComponent<SpriteRenderer>().color = playerColor;
		playerReflection.name = "PlayerReflection";
	}

	void Update () 
	{
		if(player) playerReflection.transform.position = new Vector3(player.transform.position.x * -1, player.transform.position.y, player.transform.position.z); 
		else if(!player) Reset();
	}

	IEnumerator WaitReflection()
	{
		int t = Random.Range(5, 10);
		yield return new WaitForSeconds (t);
		if(playerVelocity == 0) reflection = !reflection;
		StartCoroutine (WaitReflection());
	}
}

Здесь на основе префаба создается персонаж и его отражение. Плюс зацикленный генератор с рандомным временем от 5 до 10 секунд, он отражает управление, в том случае если герой не движется по оси Y, то есть, чтобы в прыжке не менялось управление. Кстати, по краям экрана стоит добавить коллайдеры, иначе можно выпрыгнуть за его приделы.

Если лень всё это делать, можно просто скачать проект по теме:

У вас нет доступа!

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

Офлайн
aaadrey 29 июня 2016
public void Jump()
{
body.velocity = new Vector2(0, addForce);
}
public void left()
{
if (!GameControl.reflection) horizontal = -1; else horizontal = 1;
}
пытался переделать упрвление под сенсор в ui добавил кнопку в Player2DControl скрипт выше. вешаю в кнопке на on click или event trigger . всегда выдает ошибку решение найти не получается чем может быть связанно?
UnassignedReferenceException: The variable body of Player2DControl has not been assigned.
You probably need to assign the body variable of the Player2DControl script in the inspector.


ps если вешать в он клик не префаб а player с иерархии то прыгает но ошибка остается.
кнопка налево не работает
Офлайн
Light 30 июня 2016
aaadrey, нужно писать отдельный скрипт, который будет обрабатывать нажатие UI кнопок и передавать результат в Player2DControl. Тогда управление будет работать как с клавиатуры, так и с UI.
Информация
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
  • Дешевый хостинг
  • Яндекс.Метрика