200?"200px":""+(this.scrollHeight+5)+"px");">
public var speed: int = 10;
public var gravity: int = 1;
Function Update () {
if(play){
if(Input.GetKey(KeyCode.Escape)){
Application.Quit();
}
If(grounded){
moveDirection = transform.TransformDirection(Vector3.forward);
moveDirection *= speed;
}
moveDirection.y -= gravity * Time.deltaTime;
if(Input.GetMouseButton(1)){
}
}
}
200?"200px":""+(this.scrollHeight+5)+"px");">public var play:boolean = true;
public var speed: int = 10;
public var moveDirection: Vector3;
public var grounded: boolean;
public var gravity: int = 1;
200?"200px":""+(this.scrollHeight+5)+"px");">function Update () {
200?"200px":""+(this.scrollHeight+5)+"px");">if(Input.GetMouseButton(1)){
var dx: int = Input.mousePosition.x - Screen.width / 2.0;
var dy: int = Input.mousePosition.y - Screen.height / 2.0;
var strawRadians: float = Mathf.Atan2(dx,dy);
var strawDigrees:float = 360.0 * strawRadians/(2.0*Mathf.PI);
transform.rotation.eulerAngles.y = strawDigrees;
200?"200px":""+(this.scrollHeight+5)+"px");">var controller: CharacterController = GetComponent(CharacterController);
var flags = controller.Move(moveDirection * Time.deltaTime);
grounded = (flags & CollisionFlags.CollidedBelow) != 0;
Public GameObject player;
public int speed = 5;
Void Start () {
player = (GameObject)this.gameObject;
}
If (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
}
If (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
player.transform.position -= player.transform.forward * speed * Time.deltaTime;
}
If (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
player.transform.Rotate(Vector3.down * speedRotation);
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
player.transform.Rotate(Vector3.up * speedRotation);
}
Public AnimationClip anima;
Animation.AddClip(anima, "animCube");
If (Input.GetKeyDown(KeyCode.Space))
{
player.transform.position += player.transform.up * jumpSpeed * Time.deltaTime;
}
using UnityEngine;
using System.Collections;
public class Move: MonoBehaviour {
public GameObject player;
public int speedRotation = 3;
public int speed = 5;
public AnimationClip anima;
public int jumpSpeed = 50;
Void Start () {
player = (GameObject)this.gameObject;
animation.AddClip(anima, "animCube");
}
void Update(){
if (Input.GetKey(KeyCode.W) || Input.GetKey(KeyCode.UpArrow))
{
player.transform.position += player.transform.forward * speed * Time.deltaTime;
animation.CrossFade("animCube");
}
if (Input.GetKey(KeyCode.S) || Input.GetKey(KeyCode.DownArrow))
{
player.transform.position -= player.transform.forward * speed * Time.deltaTime;
}
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
player.transform.Rotate(Vector3.down * speedRotation);
}
if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
player.transform.Rotate(Vector3.up * speedRotation);
}
if (Input.GetKeyDown(KeyCode.Space))
{
player.transform.position += player.transform.up * jumpSpeed * Time.deltaTime;
}
Функции событий
В редакторе Unity вы изменяете свойства Компонента используя окно Inspector. Так, например, изменения позиции компонента Transform приведет к изменению позиции игрового объекта. Аналогично, вы можете изменить цвет материала компонента Renderer или массу твёрдого тела (RigidBody) с соответствующим влиянием на отображение или поведение игрового объекта. По большей части скрипты также изменяют свойства компонентов для управления игровыми объектами. Разница, однако, в том, что скрипт может изменять значение свойства постепенно со временем или по получению ввода от пользователя. За счет изменения, создания и уничтожения объектов в заданное время может быть реализован любой игровой процесс.
Наиболее простым и распространенным является случай, когда скрипту необходимо обратиться к другим компонентам, присоединенных к тому же GameObject. Как упоминалось во разделе Введение, компонент на самом деле является экземпляром класса, так что первым шагом будет получение ссылки на экземпляр компонента, с которым вы хотите работать. Это делается с помощью функции GetComponent . Типично, объект компонента сохраняют в переменную, это делается в C# посредством следующего синтаксиса:
В UnityScript синтаксис немного отличается:
Function Start () {
var rb = GetComponent.
Void Start () {
Rigidbody rb = GetComponent
Дополнительная возможность, недоступная в окне Inspector - вызов функций экземпляра компонента:
Void Start () {
Rigidbody rb = GetComponent
Имейте ввиду, что нет причины, по которой вы не можете иметь больше одного пользовательского скрипта, присоединенного к одному и тому же объекту. Если вам нужно обратиться к одному скрипту из другого, вы можете использовать, как обычно, GetComponent, используя при этом имя класса скрипта (или имя файла), чтобы указать какой тип Компонента вам нужен.
Если вы попытаетесь извлечь Компонент, который не был добавлен к Игровому Объекту, тогда GetComponent вернет null; возникнет ошибка пустой ссылки при выполнении (null reference error at runtime), если вы попытаетесь изменить какие-либо значения у пустого объекта.
Пусть иногда они и существуют изолированно, все же, обычно, скрипты отслеживают другие объекты. Например, преследующий враг должен знать позицию игрока. Unity предоставляет несколько путей получения других объектов, каждый подходит для конкретной ситуации.
Самый простой способ найти нужный игровой объект - добавить в скрипт переменную типа GameObject с уровнем доступа public:
Public class Enemy: MonoBehaviour { public GameObject player; // Other variables and functions... }
Переменная будет видна в окне Inspector, как и любые другие:
Теперь вы можете перетащить объект со сцены или из панели Hierarchy в эту переменную, чтобы назначить его. Функция GetComponent и доступ к переменным компонента доступны как для этого объекта, так и для других, то есть вы можете использовать следующий код:
Public class Enemy: MonoBehaviour { public GameObject player; void Start() { // Start the enemy ten units behind the player character. transform.position = player.transform.position - Vector3.forward * 10f; } }
Кроме того, если объявить переменную с доступом public и заданным типом компонента в вашем скрипте, вы сможете перетащить любой объект, который содержит присоединенный компонент такого типа. Это позволит обращаться к компоненту напрямую, а не через игровой объект.
Public Transform playerTransform;
Соединение объектов через переменные наиболее полезно, когда вы имеете дело с отдельными объектами, имеющими постоянную связь. Вы можете использовать массив для хранения связи с несколькими объектами одного типа, но связи все равно должны быть заданы в редакторе Unity, а не во время выполнения. Часто удобно находить объекты во время выполнения, и Unity предоставляет два основных способа сделать это, описанных ниже.
Иногда игровая сцена может использовать несколько объектов одного типа, таких как враги, путевые точки и препятствия. Может возникнуть необходимость отслеживания их в определенном скрипте, который управляет или реагирует на них (например, все путевые точки могут потребоваться для скрипта поиска пути). Можно использовать переменные для связывания этих объектов, но это сделает процесс проектирования утомительным, если каждую новую путевую точку нужно будет перетащить в переменную в скрипте. Аналогично, при удалении путевой точки придется удалять ссылку на отсутствующий объект. В случаях, наподобие этого, чаще всего удобно управлять набором объектов, сделав их дочерними одного родительского объекта. Дочерние объекты могут быть получены, используя компонент Transform родителя (так как все игровые объекты неявно содержат Transform):
Using UnityEngine; public class WaypointManager: MonoBehaviour { public Transform waypoints; void Start() { waypoints = new Transform; int i = 0; foreach (Transform t in transform) { waypoints = t; } } }
Вы можете также найти заданный дочерний объект по имени, используя функцию
Предположим, что у нас есть объект, который должен двигаться к точке. Задачка-то простенькая, использовать интерполяцию, например. Но что, если наш объект может поворачиваться на случайный угол? Как тогда задать точку для интерполирования? Ведь наверняка наша условная вагонетка должна двигаться только по направлению своих колес. Соответственно либо тыльной, либо фронтальной стороной. С этой задачей нам поможет справиться векторная алгебра.Теперь мы знаем, что у нас есть вектор и нам нужно найти координаты его конца. Для однозначного решения этой задачи необходим набор параметров:
$inline$x/sin(α) = a/sin (90)$inline$
$inline$ x = a* sin(α)$inline$
$inline$y/sin (90 - α) = a/sin(90)$inline$
$inline$ y = a * sin (90 - α)$inline$
Где a - длина вектора, α - угол наклона к оси координат
Собственно, этих знаний нам пока достаточно для решения задачи на практике.
И в unity это тоже работает. Для начала, нам нужно определить четверти в сцене. Создаем куб в начале координат, перемещаем его и смотрим, какие координаты отрицательные, а какие положительные. В примере видно, что обе координаты отрицательные, значит куб находится в третьей четверти.
Теперь можно приступать непосредственно к скрипту. На вход мы принимаем Transform исходного объекта после поворота и Transform пустышки, к которой в последствии будем двигаться. Пустышка изначально имеет координаты объекта. Далее определяем четверть, в которой находится фронт объекта. Так как тригонометрическая окружность ограничена от 0 до 360 градусов, то труда это не составляет. Определив четверть, вычисляем углы наклона для каждой координаты. Потом делаем проверку, чтобы наши углы имели правильный знак. После этого отправляем углы наклона в конечную формулу вычисления координат. И наконец, задаем новые координаты пустышке, к которой будем интерполировать.
Void ChekingQuarterUp(Transform vectorAngle, ref Transform empty) { float zangle = 0; float xangle= 0; float zcoord = 0.0f; float xcoord = 0.0f; int normangle = Mathf.RoundToInt (vectorAngle.eulerAngles.y); if (normangle >= 0 && normangle <= 90) // 1-ая четверть { zangle = 90 - normangle; xangle = 0 - normangle; xangle = (xangle < 0) ? xangle * -1: xangle; zangle = (zangle < 0) ? zangle * -1: zangle; } if (normangle > 270 && normangle <= 360) // 2-ая четверть { xangle = 360 - normangle; zangle = 270 - normangle; xangle = (xangle > 0) ? xangle * -1: xangle; zangle = (zangle < 0) ? zangle * -1: zangle; } if (normangle > 180 && normangle <= 270) // 3-ая четверть { xangle = 180 - normangle; zangle = 270 - normangle; xangle = (xangle > 0) ? xangle * -1: xangle; zangle = (zangle > 0) ? zangle * -1: zangle; } if (normangle > 90 && normangle <= 180) // 4-ая четверть { zangle = 90 - normangle; xangle = 180 - normangle; zangle = (zangle > 0) ? zangle * -1: zangle; xangle = (xangle < 0) ? xangle * -1: xangle; } zcoord = path * Mathf.Sin (zangle *Mathf.PI/180); xcoord = path * Mathf.Sin (xangle * Mathf.PI/180); float newpathx = empty.position.x + xcoord; float newpathz = empty.position.z + zcoord; empty.position = new Vector3 (newpathx, empty.transform.position.y, newpathz); }
Для движения «задом» нужно всего лишь диаметрально изменить знаки координат согласно четвертям. Если вы решили определять точку в трехмерном пространстве, то учитывайте, что «четвертей» там будет больше.
Пример реализации метода можно взять
, Из песочницы
Теперь мы знаем, что у нас есть вектор и нам нужно найти координаты его конца. Для однозначного решения этой задачи необходим набор параметров:
$inline$x/sin(?) = a/sin (90)$inline$
$inline$ x = a* sin(?)$inline$
$inline$y/sin (90 - ?) = a/sin(90)$inline$
$inline$ y = a * sin (90 - ?)$inline$
Где a - длина вектора, ? - угол наклона к оси координат
Собственно, этих знаний нам пока достаточно для решения задачи на практике.
И в unity это тоже работает. Для начала, нам нужно определить четверти в сцене. Создаем куб в начале координат, перемещаем его и смотрим, какие координаты отрицательные, а какие положительные. В примере видно, что обе координаты отрицательные, значит куб находится в третьей четверти.
Теперь можно приступать непосредственно к скрипту. На вход мы принимаем Transform исходного объекта после поворота и Transform пустышки, к которой в последствии будем двигаться. Пустышка изначально имеет координаты объекта. Далее определяем четверть, в которой находится фронт объекта. Так как тригонометрическая окружность ограничена от 0 до 360 градусов, то труда это не составляет. Определив четверть, вычисляем углы наклона для каждой координаты. Потом делаем проверку, чтобы наши углы имели правильный знак. После этого отправляем углы наклона в конечную формулу вычисления координат. И наконец, задаем новые координаты пустышке, к которой будем интерполировать.
Void ChekingQuarterUp(Transform vectorAngle, ref Transform empty) { float zangle = 0; float xangle= 0; float zcoord = 0.0f; float xcoord = 0.0f; int normangle = Mathf.RoundToInt (vectorAngle.eulerAngles.y); if (normangle >= 0 && normangle <= 90) // 1-ая четверть { zangle = 90 - normangle; xangle = 0 - normangle; xangle = (xangle < 0) ? xangle * -1: xangle; zangle = (zangle < 0) ? zangle * -1: zangle; } if (normangle > 270 && normangle <= 360) // 2-ая четверть { xangle = 360 - normangle; zangle = 270 - normangle; xangle = (xangle > 0) ? xangle * -1: xangle; zangle = (zangle < 0) ? zangle * -1: zangle; } if (normangle > 180 && normangle <= 270) // 3-ая четверть { xangle = 180 - normangle; zangle = 270 - normangle; xangle = (xangle > 0) ? xangle * -1: xangle; zangle = (zangle > 0) ? zangle * -1: zangle; } if (normangle > 90 && normangle <= 180) // 4-ая четверть { zangle = 90 - normangle; xangle = 180 - normangle; zangle = (zangle > 0) ? zangle * -1: zangle; xangle = (xangle < 0) ? xangle * -1: xangle; } zcoord = path * Mathf.Sin (zangle *Mathf.PI/180); xcoord = path * Mathf.Sin (xangle * Mathf.PI/180); float newpathx = empty.position.x + xcoord; float newpathz = empty.position.z + zcoord; empty.position = new Vector3 (newpathx, empty.transform.position.y, newpathz); }
Для движения «задом» нужно всего лишь диаметрально изменить знаки координат согласно четвертям. Если вы решили определять точку в трехмерном пространстве, то учитывайте, что «четвертей» там будет больше.
Пример реализации метода можно взять