Пролог. И снова здравствуйте. Это второй урок по созданию RPG на Unity3D. Изначально я хотел написать его не много по другому но планы у меня изменились и пришлось все предумывать. Сначала задумывалось делать 2 камеры с видо от первого лица и от 3, но в итоге я оставил только от третьего. Сегодня я все скрипты покажу вам полностью сразу и постораюсь объяснить малопонятные вещи в коде дабы экономить свое время и ваше. В прошлом уроке я забыл написать о «build», то есть непосредственно компиляции проекта.По этому мы сделаем это сейчас. Откроем наш проект. Если открылась пустая сцена нажмем «Ctrl+o» и откроем сцену которую мы делали на прошлом уроке. Нажмем «Ctrl+Shift+b» и в открывшемся окне нажмем «Add Current». Это поставит наше меню в список компилирования и даст ему порядковый номер. При открытии компилированного проекта первой открывается сцена под номером 0. Если нажмем «Build And Run» наш проект скомпилируется и запустится. План урока. 1) Импорт персонажа. 2) Передвижение персонажа. 3) Настройка камеры 4) Анимация персонажа. Импорт персонажа. Сцена. Создаем «Terrain» с размерами 200х200. Вешаем какую-нибудь текстуру для удобства отображения. Создадим источник света. Персонаж Возьмем заранее подготовленного персонажа с анимациями, я взял из «Asset Store»(«Window>>Asset Store» или Ctrl+9) персонажа с названием Blade Girl NPC. Эта моделька стоит 15$ Она у меня уже есть и я буду использовать именно её. Вы можете там же поискать бесплатные(Среди них есть достойные). или же просто в интернете поискать какие нибудь. В эту модель уже впихнута анимация различных действий, атака, бег и тд. и тп. и даже танец Гангнам Стайл))). После импорта находим находим в окне «Project» префаб персонажа, у меня он называется «Balde_girl_Prefab» и находится в папке «Blade_girl». Перетаскиваем этот префаб на сцену, и видим наш персонаж, только каойто он большой через чур, это не беда. В инспекторе в пункте «Scale» выставим все по единичке, и все хорошо становиться, моделька стала нормальных размеров, можно работать дальше «Префаб — это один из типов ресурсов, предназначений для многократного использования и хранящийся в Project View. Префаб может быть вставлен в любое количество сцен и многократно в одну сцену. Когда префаб добавляется в сцену, создаётся его экземпляр. Все экземпляры являются ссылками на оригинальный префаб и фактически его клонами. Независимо от того, как много экземпляров в проекте, при изменении префаба изменяются соответственно и все его экземпляры.» Нажимаем «Add component>>Physics>>Rigidbody» и «Add component>>Physics>>Capsule Collider». В «Capsule Collider» Выставляем размеры нашей капсулы что бы получилось как на картинке, слегка чуть больше модельки самой. В «Rigidbody» ставим галочку «Use gravity». Раскрываем вкладку «Constraints» и ставим все 3 галочки на «Freeze Rotation». Это нужно для того что бы наш персонаж не проваливался сквозь землю, не падал на землю если вдруг окажется на неровности и тому подобное. Программируем персонажа на перемещение. Создадим c# скрипт «movePlayer». Код using UnityEngine; using System.Collections; public class movePlayer: MonoBehaviour { private GameObject player; //Переменна объекта персонажа с которым будем работать. public static int speed = 6; //Скорость перемещения персонажа. Запись public static обозначает что мы сможем обращаться к этой переменной из любого скрипта public static int _speed; //постоянная скорость перемещения персонажа public int rotation = 250; //Скорость пповорота персонажа public int jump = 3; //Высота прыжка public static bool IsDrawWeapon; //Двоичная переменная, которая будет отвечать достануто ли у нас оружие. public static float x = 0.0f; //угол поворота персонажа по оси x void Start () { IsDrawWeapon = false; //По умолчанию оружие у нас спрятано. _speed = speed; //Задаем постоянное стандартное значение скорости персонажа player = (GameObject)this.gameObject; //Задаем что наш персонаж это объект на котором расположен скрипт } void Update () { if(IsDrawWeapon == true) //Если оружие вытащено { speed = _speed * 2; // Меняем скорость передвижени(я это сделал потому что, у этой моделки нету анимаций движения простым шагом с мечом. а понижать скорость анимации у бега получиться не красиво) if(Input.GetKey(KeyCode.W)) //Если нажать W { player.transform.position += player.transform.forward * speed * Time.deltaTime; //Перемещаем персонажа в перед, с заданой скорость. Time.deltaTime ставится для плавного перемещения персонажа, если этого не будет он будет двигаться рывками } if(Input.GetKey(KeyCode.S)) { speed = _speed / 2; //При передвижениии назад снижаем скорость перемещения player.transform.position -= player.transform.forward * speed * Time.deltaTime; //Перемещаем назад } if(Input.GetKeyUp (KeyCode.S)) { speed = _speed * 2; //Возвращаем cтандартное значение } if(Input.GetKey (KeyCode.A)) { player.transform.position -= player.transform.right * speed * Time.deltaTime; //перемещаем в лево } if(Input.GetKey (KeyCode.D)) { player.transform.position += player.transform.right * speed * Time.deltaTime; //перемещаем в право } if(Input.GetKey (KeyCode.Space)) { player.transform.position += player.transform.up * jump * Time.deltaTime; //Прыгаем } if(Input.GetKey (KeyCode.Tab)) //При нажатии и на кнопку Tab { IsDrawWeapon = false; //Мы спрячем наше оружие. } } else if(IsDrawWeapon == false) //Если оружие не спрятано. Сделано разделение на движения в зависимости от того вытащено ли у нас оружие или нет, потому что персонаж будет перемещаться сразной скорость у меня в этих случаях, как я уже написал из за отсутсвия некоторых анимаций у модельки. { speed = _speed;//Скорость в стандартное значение if(Input.GetKey (KeyCode.LeftShift)) //Если зажать левый Shift { speed = _speed * 2; //Увеличиваем скорость перемещения(бег) } if(Input.GetKeyUp (KeyCode.LeftShift)) //Если отпустить { speed = _speed; //Возвращаем стандартное значение } if(Input.GetKey(KeyCode.W)) //Если нажать W { player.transform.position += player.transform.forward * speed * Time.deltaTime; //Перемещаем персонажа в перед. } if(Input.GetKey(KeyCode.S)) { speed = _speed / 2; player.transform.position -= player.transform.forward * speed * Time.deltaTime; //Перемещаем назад } if(Input.GetKeyUp (KeyCode.S)) { speed = _speed; //Возвращаем cтандартное значение } if(Input.GetKey (KeyCode.A)) { player.transform.position -= player.transform.right * speed * Time.deltaTime; //перемещаем в лево } if(Input.GetKey (KeyCode.D)) { player.transform.position += player.transform.right * speed * Time.deltaTime; //перемещаем в право } if(Input.GetKey (KeyCode.Space)) { player.transform.position += player.transform.up * jump * Time.deltaTime; //Прыгаем } if(Input.GetKey (KeyCode.Tab)) //при нажатии на кнопку таб { IsDrawWeapon = true; //Мы вытащим наше оружие } } //Поворачиваем персонажа. Так как наша переменная x глобальна, из скрипта камеры в неё будем записывать длину на сколько сместился указатель мыши и по оси X и относительно этого будет повернут наш персонаж Quaternion rotate = Quaternion.Euler (0,x,0); //Создаем новую переменную типа Quaternion для задавания угла поворота player.transform.rotation = rotate; //Поворачиваем персонаж } } Скрипт помещаем на персонажа. Управление камерой. Создадим еще один c# скрипт, и назовем его «moveCam» Код codeusing UnityEngine; using System.Collections; public class CamMove: MonoBehaviour { public Transform target; //Объект за которым летаем(Наш персонаж) public float distance = 3.0f; //На каком ратоянии от него public float xSpeed = 125.0f; //Чуствительность по Х public float ySpeed = 50.0f; //Y Чуствительность public float targetHeight = 2.0f; //Высота относительно объекта //Минимальный и максимальный угол поворота Y инче камеру разверет, Дальше у нас будет простая функция для инвертации их в обратные числа public float yMinLimit = -40; public float yMaxLimit = 80; //Максимальное удаление и приближение камеры к персонажу, искорость. public float maxDistance = 10.0f; public float minDistance = 0.5f; public float zoomRote = 90.0f; private float x = 0.0f; //Угол поворота по Y? private float y = 0.0f; //Уго поворота по X? [AddComponentMenu("Scripts/Mouse Orbit")] //Добавляем в меню public void Start() { //переворачивам углы Vector3 angles = transform.eulerAngles; x = angles.y; y = angles.x; if(rigidbody) rigidbody.freezeRotation = true; //Если камера столкнется с физ.объектомона остановиться } public void LateUpdate() { if (target) {//Если цель установлена(Персонаж) //Меняем углы согласно положению мыши x += Input.GetAxis("Mouse X") * xSpeed * 0.02f; y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f; //Меняем дистанция до персонажа. distance -= (Input.GetAxis ("Mouse ScrollWheel") * Time.deltaTime) * zoomRote * Mathf.Abs(distance); distance = Mathf.Clamp (distance, minDistance, maxDistance); y = ClampAngle(y,yMinLimit, yMaxLimit); //Вызыв самописной функции для ограничения углов поврот movePlayer.x = x; //Повернуть камеру согласно поченым данным Quaternion rotation = Quaternion.Euler(y, x, 0); transform.rotation = rotation; //Двигаем камеру и следим за персонажем Vector3 position = rotation * new Vector3(0.0f, targetHeight+0.5f, -distance) + target.position; transform.position = position; //Следуйщи код нужен что бы камера не проваливалась по ланшафт RaycastHit hit; Vector3 trueTargetPosition = target.transform.position - new Vector3(0, -targetHeight,0); if(Physics.Linecast (trueTargetPosition, transform.position, out hit)) { float tempDistance = Vector3.Distance (trueTargetPosition, hit.point) - 0.28f; position = target.position - (rotation * Vector3.forward * tempDistance + new Vector3(0, -targetHeight, 0)); transform.position = position; } } } //Меняем значения углов public static float ClampAngle (float angle, float min, float max) { if(angle < -360) angle += 360; if(angle > 360) angle -= 360; return Mathf.Clamp (angle, min, max); } } Скрипт кидаем на камеру. Камера должна быть перемещена в префаб персонажа в окне «Hierarchy». А в компоненте скрипта на камере в поле «Target» долже быть помещен наш префаб из окна «Hierarchy». Анимация Создадим новый скрипт и назовем его «AnimatePlayer» Код using UnityEngine; using System.Collections; public class AnimatePlayer: MonoBehaviour { public void Start () { // Устанавливаем все клипы анимации в режим цикла animation.wrapMode = WrapMode.Loop; // Кроме следующих animation["Attack01"].wrapMode = WrapMode.Once; animation["jump"].wrapMode = WrapMode.Once; animation["Skill"].wrapMode = WrapMode.Once; //У них одиночное выполнение //Останавливаем выполнение анимаций. animation.Stop(); } public void Update () { // На основе нажатой клавиши выполняем анимацию if(movePlayer.IsDrawWeapon == false) //Если оружие не вытащено { if (Input.GetAxis("Vertical") > 0.0f) //Проверяем на изминениея позиции персонажа повертикали, если да { if(movePlayer.speed == movePlayer._speed * 2) //Проверяем скорость Передвижения персонажа, { animation.CrossFade ("Run00"); //Если зажата клавиша shift, значит грузим анимацию бега } else { animation.CrossFade("Walk"); //В противном случаее ходьбу } } else if(Input.GetAxis("Vertical") < 0.0f) //Далее все по анологии { if(movePlayer.speed == movePlayer._speed * 2) { animation.CrossFade ("B_Run00"); //бег назад } else { animation.CrossFade ("B_Walk"); //ходьба назад } } else if (Input.GetAxis("Horizontal") > 0.0f) { if(movePlayer.speed == movePlayer._speed * 2) { animation.CrossFade ("R_Run00"); //бег в право } else { animation.CrossFade ("R_Walk"); //Шагание в право } } else if(Input.GetAxis("Horizontal") < 0.0f) { if(movePlayer.speed == movePlayer._speed * 2) { animation.CrossFade ("L_Run00"); //лево } else { animation.CrossFade ("L_Walk"); //лево } } else if(Input.GetKey (KeyCode.Space)) //если сделан прыжок { animation.Play ("Jump_NoBlade"); //Включаем анимацию прыжка } else { animation.CrossFade("Idle"); //просто стоим } } else if(movePlayer.IsDrawWeapon == true) //если оружие вытащено { if (Input.GetAxis("Vertical") > 0.0f) { animation.CrossFade ("Run"); //бег в перед } else if(Input.GetAxis("Vertical") < 0.0f) { animation.CrossFade ("B_Run"); //назад } else if (Input.GetAxis("Horizontal") > 0.0f) { animation.CrossFade ("R_Run"); //в право } else if(Input.GetAxis("Horizontal") < 0.0f) { animation.CrossFade ("L_Run"); //в лево } else if(Input.GetKey (KeyCode.Space)) { animation.Play ("jump"); //Прыжок } else { animation.CrossFade("AttackStandy"); //просто стоим } //Анимация атаки if (Input.GetMouseButton (0)) //Если нажать маус 1 animation.CrossFade("Attack01"); //Включаем анимацию атаки if (Input.GetMouseButton (1)) //Если нажать маус 2 animation.CrossFade("Skill"); //Включаем анимацию скила } } } Скрипт должен быть помещен на персонажа. В окне «Project» создадим папку «Prefab» и перетащим в нее префаб персонажа из окна «Hierarchy» что бы сохранить все на будущее и не повторять все заново. На сегодня все всем надеюсь моя статья вам будет полезна. |