Перейти к содержанию

Проблемка из созданием телепорта


Рекомендуемые сообщения

Доброго времени суток всем.

Решил я попробовать найти координаты игрока в игре "Lifeless Planet", сначала я пробовал найти высоту то есть ось Z, но среди адресов которые остались в процессе отсева я нашел ось X, после заморозки этой оси я не смог в игре идти назад или вперед.

921e32216909.png

Я поставил бряк на доступ и вот что получилось:

97863d481a83.png

Странно то, что адрес который я нашел не получает доступ ни к одной из этих инструкций.

И моего адреса там нет, нигде, ни в единой инструкции, вот что получалось когда я находил адреса получающие доступ к любой инструкции что выше, моего адреса там не оказалось (мой адрес 0EA2D244):

3fdc14b08379.png

Я сначала подумал что возможно это другие оси, но заморозка этих значений мне ничего не дало. Я попробовал заглянуть в структуру одной из тех инструкций и вот что получилось:

9c9ce7a34796.png

Как вы видите мой адрес находиться со смещением 14, я взял адрес со смещением 10,8,4,0,18,1С и тд. и тп. но среди них не оказалось нужных мне осей Y и Z, почему же в игре координаты не находятся рядом друг от друга с интервалом по смещению и почему когда я хотел найти адреса которые получают доступ к любой инструкции ,- своего адреса я там не нашел???? ну и как мне найти остальные координаты???

Потом после этого я пробовал найти остальные координаты вручную но в итоге после отсева оставалось адресов 400-600.

Ссылка на комментарий
Поделиться на другие сайты

Никогда с таким не сталкивался, возможно мастера помогут... Может посмотреть на инструкции выше/ниже, в отладчике, вдруг там есть что-то, за что можно зацепиться? -_-

Ссылка на комментарий
Поделиться на другие сайты

Никогда с таким не сталкивался, возможно мастера помогут... Может посмотреть на инструкции выше/ниже, в отладчике, вдруг там есть что-то, за что можно зацепиться? :sleep:

Сначала дайте новичку попробовать :-D

Ссылка на комментарий
Поделиться на другие сайты

Типичная путаница в типах значений.

Адрес найденный - 0EA2D244.

Инструкции нашлись правильно, но при проверке оказалось, что, оказывается, с этим адресом якобы инструкция не работает. Но, если посмотреть на один адрес из списка, то мы видим

0EA2D240, отличающийся от найденного на четыре байта. Отсюда можно сделать вывод, что тип значения найденного был задан неверно, и нужно брать тип вдвое больше заданного. Стало быть, правильный тип координаты получается double, и настоящий адрес координаты именно 0EA2D240. Это же подтверждает и найденная отладчиком инструкция

movq xmm0,[esi+00000108], что значит move quad word.

Ссылка на комментарий
Поделиться на другие сайты

Типичная путаница в типах значений.

Адрес найденный - 0EA2D244.

Инструкции нашлись правильно, но при проверке оказалось, что, оказывается, с этим адресом якобы инструкция не работает. Но, если посмотреть на один адрес из списка, то мы видим

0EA2D240, отличающийся от найденного на четыре байта. Отсюда можно сделать вывод, что тип значения найденного был задан неверно, и нужно брать тип вдвое больше заданного. Стало быть, правильный тип координаты получается double, и настоящий адрес координаты именно 0EA2D240. Это же подтверждает и найденная отладчиком инструкция

movq xmm0,[esi+00000108], что значит move quad word.

Ну вот, как я и говорил, мастера помогут :)

А у меня вопрос по поводу проблемы ТС - почему адреса при заморозке не хотели замораживаться? Это также связано с типами? Но мы ведь меняем тип найденного значения в СЕ, а не в самой игре, то есть, отослав значение - игра, как мне кажется, должна "подогнать" это значение под то, какое ей больше подходит (целочисленное, с плавающей точкой и т.д.).

Или проблема кроется именно в СЕ, что из-за неверного типа, он работает с адресом неправильно?

Ссылка на комментарий
Поделиться на другие сайты

Типичная путаница в типах значений.

Адрес найденный - 0EA2D244.

Инструкции нашлись правильно, но при проверке оказалось, что, оказывается, с этим адресом якобы инструкция не работает. Но, если посмотреть на один адрес из списка, то мы видим

0EA2D240, отличающийся от найденного на четыре байта. Отсюда можно сделать вывод, что тип значения найденного был задан неверно, и нужно брать тип вдвое больше заданного. Стало быть, правильный тип координаты получается double, и настоящий адрес координаты именно 0EA2D240. Это же подтверждает и найденная отладчиком инструкция

movq xmm0,[esi+00000108], что значит move quad word.

А нужные инструкции, которые загружают значения координат XYZ соответственно:


004842EB - DD 00 - fld qword ptr [eax]
004842F3 - DD 40 08 - fld qword ptr [eax+08]
004842F9 - DD 40 10 - fld qword ptr [eax+10]

Если править значения double по адресам eax 0 +8 +10 происходит перемещение в заданные мировые координаты.

Можно писать телепорт)

Ну вот, как я и говорил, мастера помогут :)

А у меня вопрос по поводу проблемы ТС - почему адреса при заморозке не хотели замораживаться? Это также связано с типами? Но мы ведь меняем тип найденного значения в СЕ, а не в самой игре, то есть, отослав значение - игра, как мне кажется, должна "подогнать" это значение под то, какое ей больше подходит (целочисленное, с плавающей точкой и т.д.).

Или проблема кроется именно в СЕ, что из-за неверного типа, он работает с адресом неправильно?

Всё морозится нормально в типе double

Ссылка на комментарий
Поделиться на другие сайты

Я сначала подумал что возможно это другие оси, но заморозка этих значений мне ничего не дало. Я попробовал заглянуть в структуру одной из тех инструкций и вот что получилось:

Получается, что не морозилось.

У меня в общем-то тоже была похожая проблема, что находил вроде правильный адрес (т.е. менял его - в игре это все правилось), а вот не замораживался он, и все тут... Потом, сменив тип (вроде-бы... не помню уже :) ), адрес заморозился правильно. Вот мне и интересно узнать было бы о данном явлении, кто виноват :)

Ссылка на комментарий
Поделиться на другие сайты

Если в СЕ задан тип неправильно, то и заморозить он не сможет в тех случаях, когда тип, как и в данном случае, вдвое больше указанного. Часть одна замораживается, а вторая - нет. Или же просто вообще заморозка не срабатывает.

Ссылка на комментарий
Поделиться на другие сайты

Если в СЕ задан тип неправильно, то и заморозить он не сможет в тех случаях, когда тип, как и в данном случае, вдвое больше указанного. Часть одна замораживается, а вторая - нет. Или же просто вообще заморозка не срабатывает.

Я в принципе так и думал, что корень зла в путанице работы адреса кроется в типе, указанном в СЕ. :) Правда, кроме этой мысли, я чуть-ли не целую теорию слепил, вплоть до бракованных планок ОЗУ :D

Ссылка на комментарий
Поделиться на другие сайты

От души спасибо за помощь, я просто читал ваши статьи и про такие проблемы там ни слова не было и это загнало меня в тупик. Большое спасибо теперь разобрался)))))

Ссылка на комментарий
Поделиться на другие сайты

Игра сделана на Unity3d. В каталоге с игрой обычно одна папка "название игры_Data" в ней папка "Managed" и там обязательно есть файл "Assembly-CSharp.dll" Это .net сборка, которая содержит практически всю логику игры и её объектов. Обычно она декомпилируется, но часто её обратно перекомпоновать нельзя из-за большого количества ошибок. Если научится загружать .net сборки в саму игру, то предположительно можно наделать много интересных читов к игре сделанной на Unity3d.

У меня уже же есть два скрипта, которые могут работать на играх Unity3d с видом от первого лица. Это полет камерой и телепорт.

Я сегодня пол дня проковырялся и ни как не могу подгрузить Cheat.dll (.net сборку) с читами изнутри этой игры.

По идее надо выполнить код ниже внутри самой игры с вызовом функции (на C++ аналог функции - точки входа в dll-ку)


Assembly a = Assembly.Load("Cheat.dll");
System.Type myType = a.GetType("Cheats");
MethodInfo myMethod = myType.GetMethod("Main");
object obj = System.Activator.CreateInstance(myType);
myMethod.Invoke(obj, null);

Я вызывал этот код из самой Unity3d на тестовом проекте и dll-ка дотнетовская загружалась, чит работал, надпись зеленная горела. Значит осталось как-то исполнить этот код изнутри самой игры... Если кто в курсе как это сделать, то дайте знать.

Что делает вызов Майн-функции? Эта функция должна создать пустой GameObject и прицепить на него него поведение-скрипт позволяющий сохранять и загружать позиции.


public class Cheats{
public static void Main(){
GameObject go = new GameObject();
go.name = "Cheats";
go.AddComponent<Teleport>();
}
}

Ну и вот класс телепорта в этой ддлке, который предположительно должен заработать или хотя бы загореться зеленная надпись в левом верхнем углу экрана. Функции Update() и OnGUI() уже будут вызываться самой игрой за кадр отрисовки.


using UnityEngine;
using System.Collections;
public class Teleport : MonoBehaviour {
Transform trCharacter;
#region MonoBehaviour
void Start() {
trCharacter = FindFirstCharacterController().transform;
}
void OnGUI(){
GUI.color = Color.green;
GUILayout.Label("Gamehacklab.ru");
}
void Update() {
//Save : "KeyCode.F1"
if(Input.GetKey(KeyCode.F1)){
if(trCharacter == null){
trCharacter = FindFirstCharacterController().transform;
}
if(trCharacter != null){
PlayerPrefs.SetString("Character Position", Vector3ToString(trCharacter.position));
PlayerPrefs.SetString("Character Rotation", Vector3ToString(trCharacter.eulerAngles));
}
}
//Load : "KeyCode.F2"
if(Input.GetKey(KeyCode.F2)){
if(trCharacter == null){
trCharacter = FindFirstCharacterController().transform;
}
if(trCharacter != null && PlayerPrefs.HasKey("Character Position") && PlayerPrefs.HasKey("Character Rotation")){
trCharacter.position = StringToVector3(PlayerPrefs.GetString("Character Position"));
trCharacter.eulerAngles = StringToVector3(PlayerPrefs.GetString("Character Rotation"));
}
}
}
#endregion
CharacterController FindFirstCharacterController(){
Object[] gos = GameObject.FindObjectsOfType(typeof(GameObject));
foreach (Object item in gos) {
if((item as GameObject).GetComponent<CharacterController>() != null){
return (item as GameObject).GetComponent<CharacterController>();
}
}
return null;
}
Vector3 StringToVector3(string argString){
string[] values = argString.Split(';');
return new Vector3 (float.Parse(values[0]), float.Parse(values[1]),float.Parse(values[2]));
}
string Vector3ToString(Vector3 argVector3){ return string.Format("{0};{1};{2}", argVector3.x, argVector3.y, argVector3.z);}
}

-----

Есть программа Titanium 0.01. Поковырявшись в ней я так понял, что она использует моно функции, которые подгружают ддлки из той же папки Managed. Но мне кажется есть несколько способов и этот не самый лучший.

Ссылка на комментарий
Поделиться на другие сайты

За подсказку спасибо. Я посмотрю позже, сейчас на отдых.

Как говориться если долго мучиться, что-нибудь получиться. В общем телепорт получился. Летающая камера получилась криво, но летает. С камерой надо будет уточнять, какой игровой скрипт выключить, чтобы он не двигал камеру....

post-3-0-37081200-1402242308_thumb.jpg

post-3-0-64856100-1402242314_thumb.jpg

Устав искать решение по загрузчику, я использовал титаниум. Поковырял его, нашел имя процесса. Переименовал игру в rust.exe и папку на "rust_Data" . В файле настроек Loader.ini ввел

[Titanium]

module_name=Cheat.dll

namespace=NamespaceCheats

class=Cheats

function=Main

Скрипт создающий чит-объект


using System;
using UnityEngine;
namespace NamespaceCheats{
public class Cheats{
public static void Main(){
GameObject go = new GameObject();
go.name = "Cheats";
go.AddComponent<Teleport>();
go.AddComponent<CheatFlyCamera>();
}
}
}

Два чита сделанные можно сказать "по интуиции", т.к. нет исходников игры (телепорт прокатил, а камера нет):


using UnityEngine;
using System.Collections;
public class Teleport : MonoBehaviour {
Transform trCharacter;
string savePosition = "unknow position";

#region MonoBehaviour
void Awake(){
DontDestroyOnLoad(this);
}

void Start() {
trCharacter = FindFirstCharacterController().transform;
}
void OnGUI(){
GUI.color = Color.green;a
GUILayout.BeginHorizontal();
GUILayout.Label("Teleport: ");
GUILayout.Label(savePosition);
GUILayout.EndHorizontal();
}
void Update() {
//Save : "KeyCode.F1"
if(Input.GetKey(KeyCode.F1)){
if(trCharacter == null){
trCharacter = FindFirstCharacterController().transform;
}
if(trCharacter != null){
savePosition = Vector3ToString(trCharacter.position);
PlayerPrefs.SetString("Character Position", Vector3ToString(trCharacter.position));
PlayerPrefs.SetString("Character Rotation", Vector3ToString(trCharacter.eulerAngles));
}
}
//Load : "KeyCode.F2"
if(Input.GetKey(KeyCode.F2)){
if(trCharacter == null){
trCharacter = FindFirstCharacterController().transform;
}
if(trCharacter != null && PlayerPrefs.HasKey("Character Position") && PlayerPrefs.HasKey("Character Rotation")){
trCharacter.position = StringToVector3(PlayerPrefs.GetString("Character Position"));
trCharacter.eulerAngles = StringToVector3(PlayerPrefs.GetString("Character Rotation"));
}
}
}
#endregion
CharacterController FindFirstCharacterController(){
Object[] gos = GameObject.FindSceneObjectsOfType(typeof(GameObject));
foreach (Object item in gos) {
if((item as GameObject).GetComponent<CharacterController>() != null){
return (item as GameObject).GetComponent<CharacterController>();
}
}
return null;
}
Vector3 StringToVector3(string argString){
string[] values = argString.Split(';');
return new Vector3 (float.Parse(values[0]), float.Parse(values[1]),float.Parse(values[2]));
}
string Vector3ToString(Vector3 argVector3){ return string.Format("{0};{1};{2}", argVector3.x, argVector3.y, argVector3.z);}
}


using UnityEngine;
using System.Collections;
public class CheatFlyCamera : MonoBehaviour {
public KeyCode keyActivated = KeyCode.CapsLock;
public float acceleration = 2f, minSpeed = 1f, maxSpeed = 20f;
public float mouseSensitivityX = 1f, mouseSensitivityY = 1f;
//public GUIStyle guiStyle;
float speed = 1f, rotationY = 0f;
Transform cameraTransform;
bool isActive;
GameObject goPerson = null;
bool[] lastState = null;

void UpdateFindObjects(){
if(cameraTransform == null){
cameraTransform = Camera.main.transform;
if(cameraTransform == null){
cameraTransform = Camera.mainCamera.transform;
}
}
if(goPerson == null){
//goPerson = GameObject.Find("3rd Person Controller");
goPerson = CheatBaseFunction.FindFirstComponent<CharacterController>().gameObject;
}
}


#region MonoBehavior
void Awake(){
DontDestroyOnLoad(this);
}
void Start(){
UpdateFindObjects();
}
void OnGUI(){
GUILayout.BeginVertical();
GUILayout.Space(20f);
GUILayout.Label("Press \"Caps Lock\" Button"); //guiStyle
GUILayout.EndVertical();
}
void Update(){
// if(Input.GetKeyDown(KeyCode.Escape)){
// Application.Quit();
// }

if(Input.GetKeyDown(keyActivated)){
UpdateFindObjects();
if(goPerson != null && cameraTransform != null){
isActive = !isActive;
goPerson.SetActiveRecursively(!isActive);

if(goPerson.active){
if(lastState != null && lastState.Length > 0){
CheatBaseFunction.RestoreStateComponents(cameraTransform.gameObject, lastState);
}
}else{
CheatBaseFunction.SetStateComponents(cameraTransform.gameObject, false, out lastState);
}
}
}
if(isActive){
bool isSomeKey = false;
float timePerFrame = Time.deltaTime;
if(Input.GetKey(KeyCode.W)){
UpdateFindObjects();
if(goPerson == null || cameraTransform == null){
return;
}
isSomeKey = true;
speed += acceleration * timePerFrame;
speed = Mathf.Clamp(speed + timePerFrame, minSpeed, maxSpeed);
cameraTransform.position += ImullQuaternionToPpoint(cameraTransform.localRotation, Vector3.forward * speed * timePerFrame);
}
if(Input.GetKey(KeyCode.A)){
UpdateFindObjects();
if(goPerson == null || cameraTransform == null){
return;
}
isSomeKey = true;
speed += acceleration * timePerFrame;
speed = Mathf.Clamp(speed + timePerFrame, minSpeed, maxSpeed);
cameraTransform.position += ImullQuaternionToPpoint(cameraTransform.localRotation, Vector3.left * speed * timePerFrame);
}
if(Input.GetKey(KeyCode.D)){
UpdateFindObjects();
if(goPerson == null || cameraTransform == null){
return;
}
isSomeKey = true;
speed += acceleration * timePerFrame;
speed = Mathf.Clamp(speed + timePerFrame, minSpeed, maxSpeed);
cameraTransform.position += ImullQuaternionToPpoint(cameraTransform.localRotation, Vector3.right * speed * timePerFrame);
}
if(Input.GetKey(KeyCode.S)){
UpdateFindObjects();
if(goPerson == null || cameraTransform == null){
return;
}
isSomeKey = true;
speed += acceleration * timePerFrame;
speed = Mathf.Clamp(speed + timePerFrame, minSpeed, maxSpeed);
cameraTransform.position += ImullQuaternionToPpoint(cameraTransform.localRotation, Vector3.back * speed * timePerFrame);
}
if(Input.GetKey(KeyCode.Space)){
UpdateFindObjects();
if(goPerson == null || cameraTransform == null){
return;
}
isSomeKey = true;
speed += acceleration * timePerFrame;
speed = Mathf.Clamp(speed + timePerFrame, minSpeed, maxSpeed);
Vector3 pos = cameraTransform.position;
pos.y += speed * timePerFrame;
cameraTransform.position = pos;
}
if(!isSomeKey){
speed = Mathf.Lerp(speed, minSpeed, timePerFrame);
}
UpdateFindObjects();
if(goPerson == null || cameraTransform == null){
return;
}
float rotationX = cameraTransform.localEulerAngles.y + Input.GetAxis("Mouse X") * mouseSensitivityX;
rotationY += Input.GetAxis("Mouse Y") * mouseSensitivityY;
rotationY = Mathf.Clamp (rotationY, -90f, 90f);
cameraTransform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
}
}
#endregion
public Vector3 ImullQuaternionToPpoint(Quaternion rotation, Vector3 point)
{
float num = rotation.x * 2f;
float num2 = rotation.y * 2f;
float num3 = rotation.z * 2f;
float num4 = rotation.x * num;
float num5 = rotation.y * num2;
float num6 = rotation.z * num3;
float num7 = rotation.x * num2;
float num8 = rotation.x * num3;
float num9 = rotation.y * num3;
float num10 = rotation.w * num;
float num11 = rotation.w * num2;
float num12 = rotation.w * num3;
Vector3 result;
result.x = (1f - (num5 + num6)) * point.x + (num7 - num12) * point.y + (num8 + num11) * point.z;
result.y = (num7 + num12) * point.x + (1f - (num4 + num6)) * point.y + (num9 - num10) * point.z;
result.z = (num8 - num11) * point.x + (num9 + num10) * point.y + (1f - (num4 + num5)) * point.z;
return result;
}

}


using UnityEngine;
using System.Collections;
public static class CheatBaseFunction {
public static T FindFirstComponent<T>() where T : Component{
Object[] gos = GameObject.FindSceneObjectsOfType(typeof(GameObject));
foreach (Object item in gos) {
if((item as GameObject).GetComponent<T>() != null){
return (item as GameObject).GetComponent<T>();
}
}
return null;
}


public static void SetStateComponents(GameObject go, bool newState, out bool[] lastState){
Component[] components = go.GetComponents(typeof(Behaviour));
int max = components.Length;
lastState = new bool[max];
for (int i = 0; i < max; i++) {
lastState[i] = (components[i] as Behaviour).enabled;
(components[i] as Behaviour).enabled = newState;
}
}

public static void RestoreStateComponents(GameObject go, bool[] lastState){
Component[] components = go.GetComponents(typeof(Behaviour));
int max = lastState.Length;
if(components.Length == max){
for (int i = 0; i < max; i++) {
(components[i] as Behaviour).enabled = lastState[i];
}
}
}
}

Кстати этот код выше, который я написал на самом деле только кажется большим. Я на работе, когда задание дают пишу гораздо больше.

А вот, что можно делать скриптами Unity3d в чужой игре вызывая стандартные скриптовые функции описанные в документации на официальном сайте. Кнопки, менюшки это все стандартные функции класса GUI

На видео мультиплеррная игра Rust (вроде валяется на Стиме). Я знаю, что мы не ломаем мультиплеерные игры и не обсуждаем, но более наглядного видео я не нашел. В сингловых играх можно теоритически делать абсолютно тоже самое и даже еще больше и это будет прикольно.

На данный момент количество игр на Unity3d растет. Думаю вскоре будут интересные игры и на Windows.

Ссылка на комментарий
Поделиться на другие сайты

Игра сделана на Unity3d. В каталоге с игрой обычно одна папка "название игры_Data" в ней папка "Managed" и там обязательно есть файл "Assembly-CSharp.dll" Это .net сборка, которая содержит практически всю логику игры и её объектов. Обычно она декомпилируется, но часто её обратно перекомпоновать нельзя из-за большого количества ошибок. Если научится загружать .net сборки в саму игру, то предположительно можно наделать много интересных читов к игре сделанной на Unity3d.

У меня уже же есть два скрипта, которые могут работать на играх Unity3d с видом от первого лица. Это полет камерой и телепорт.

Я сегодня пол дня проковырялся и ни как не могу подгрузить Cheat.dll (.net сборку) с читами изнутри этой игры.

По идее надо выполнить код ниже внутри самой игры с вызовом функции (на C++ аналог функции - точки входа в dll-ку)


Assembly a = Assembly.Load("Cheat.dll");
System.Type myType = a.GetType("Cheats");
MethodInfo myMethod = myType.GetMethod("Main");
object obj = System.Activator.CreateInstance(myType);
myMethod.Invoke(obj, null);

Я вызывал этот код из самой Unity3d на тестовом проекте и dll-ка дотнетовская загружалась, чит работал, надпись зеленная горела. Значит осталось как-то исполнить этот код изнутри самой игры... Если кто в курсе как это сделать, то дайте знать.

Что делает вызов Майн-функции? Эта функция должна создать пустой GameObject и прицепить на него него поведение-скрипт позволяющий сохранять и загружать позиции.


public class Cheats{
public static void Main(){
GameObject go = new GameObject();
go.name = "Cheats";
go.AddComponent<Teleport>();
}
}

Ну и вот класс телепорта в этой ддлке, который предположительно должен заработать или хотя бы загореться зеленная надпись в левом верхнем углу экрана. Функции Update() и OnGUI() уже будут вызываться самой игрой за кадр отрисовки.


using UnityEngine;
using System.Collections;
public class Teleport : MonoBehaviour {
Transform trCharacter;
#region MonoBehaviour
void Start() {
trCharacter = FindFirstCharacterController().transform;
}
void OnGUI(){
GUI.color = Color.green;
GUILayout.Label("Gamehacklab.ru");
}
void Update() {
//Save : "KeyCode.F1"
if(Input.GetKey(KeyCode.F1)){
if(trCharacter == null){
trCharacter = FindFirstCharacterController().transform;
}
if(trCharacter != null){
PlayerPrefs.SetString("Character Position", Vector3ToString(trCharacter.position));
PlayerPrefs.SetString("Character Rotation", Vector3ToString(trCharacter.eulerAngles));
}
}
//Load : "KeyCode.F2"
if(Input.GetKey(KeyCode.F2)){
if(trCharacter == null){
trCharacter = FindFirstCharacterController().transform;
}
if(trCharacter != null && PlayerPrefs.HasKey("Character Position") && PlayerPrefs.HasKey("Character Rotation")){
trCharacter.position = StringToVector3(PlayerPrefs.GetString("Character Position"));
trCharacter.eulerAngles = StringToVector3(PlayerPrefs.GetString("Character Rotation"));
}
}
}
#endregion
CharacterController FindFirstCharacterController(){
Object[] gos = GameObject.FindObjectsOfType(typeof(GameObject));
foreach (Object item in gos) {
if((item as GameObject).GetComponent<CharacterController>() != null){
return (item as GameObject).GetComponent<CharacterController>();
}
}
return null;
}
Vector3 StringToVector3(string argString){
string[] values = argString.Split(';');
return new Vector3 (float.Parse(values[0]), float.Parse(values[1]),float.Parse(values[2]));
}
string Vector3ToString(Vector3 argVector3){ return string.Format("{0};{1};{2}", argVector3.x, argVector3.y, argVector3.z);}
}

-----

Есть программа Titanium 0.01. Поковырявшись в ней я так понял, что она использует моно функции, которые подгружают ддлки из той же папки Managed. Но мне кажется есть несколько способов и этот не самый лучший.

Пили видос по Unity3D :-D

Ссылка на комментарий
Поделиться на другие сайты

post-3-0-58154600-1402504542_thumb.jpg

Привет детишки и взрослые! :-D Сегодня после работы написал скриптец (ниже) показывающий иерархию объектов игры и связанные компоненты во время игры и на любой сцене с обновлением в 5 секунд + копирование лога данных. Лог в аттаче.

Из компонентов можно найти стандартные и нестандартные. В данном случае видны названия объектов и связи между ними. Если отключить родительский, то отключатся и дочерние. У отключенных игровых объектов перестают работать скрипты.


using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Text;

public class ProviderHierarchy : MonoBehaviour {
#region Types
public class Data{
public Transform tr;
public bool isShow;
public string caption;
public List<Data> tree = new List<Data>();

public Data(Transform tr, string caption){ this.tr = tr; this.caption = caption;}
public void Add(Data data){ tree.Add(data);}
public void Add(Transform tr, string caption){tree.Add(new Data(tr, caption));}

public void OnGUI(ref Rect parentRect, float dx, float dy, float dx1, float dy1){
float lastX = parentRect.x;
parentRect.x = parentRect.x + dx;
parentRect.y = parentRect.y + dy;
GUI.Label(parentRect, caption);
parentRect.x += dx1;
foreach (Data item in tree) {
parentRect.y += dy1;
item.OnGUI(ref parentRect, dx, dy, dx1, dy1);
}
parentRect.x = lastX;
}
}
#endregion

public Rect rectWindow = new Rect(10f, 34.5f, 500f, 700f), rectBtnCopy; = new Rect(0f, 0f, 120f, 30f);
public string caption = "Tree view";
public float timeUpdate = 5f, dx = 0.7f, dy = 1.72f, dx1 = 10f, dy1 = 12.45f;
float lstTime;
List<Transform> trList = new List<Transform>();
public Rect rectView, parentRect;
Data treeData = null;
Vector2 scrollView;

#region MonoBehaviour
void Awake(){
DontDestroyOnLoad(this);
}
void Start(){
rectView = rectWindow;
rectView.x += 20f;
rectView.y += 20f;
rectView.width -= 40f;
rectView.height -= 40f;
UpdateTreeView();
}
void OnGUI(){
if(treeData == null || isCopyText)
return;

GUI.Box(rectView, caption);
rectWindow.height = parentRect.y + 10f;
scrollView = GUI.BeginScrollView(rectView, scrollView, rectWindow , true, true);
parentRect = new Rect(rectView.x + 10f,
rectView.y,
rectView.width - 10f,
rectView.height - 10f);
treeData.OnGUI(ref parentRect, dx, dy, dx1, dy1);
GUI.EndScrollView();
if(GUI.Button(rectBtnCopy, "Coppy To Buffer")){
System.Type T = typeof(GUIUtility);
System.Reflection.PropertyInfo systemCopyBufferProperty = T.GetProperty("systemCopyBuffer", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
systemCopyBufferProperty.SetValue(null, GetTextInfo().ToString(), null);
}
}
void Update(){
if(isCopyText){
return;
}
lstTime += Time.deltaTime;
if(lstTime > timeUpdate){
lstTime = 0f;
UpdateTreeView();
}
}
#endregion

#region MyRegion
void UpdateTreeView(){
Object[] objects = FindObjectsOfType(typeof(GameObject));

trList = new List<Transform>();
foreach (Object item in objects) trList.Add((item as GameObject).transform);

//Собрать объекты у которых нет родителей и есть родители
List<Transform> parentList = new List<Transform>();
List<Transform> childsList = new List<Transform>();
foreach (Transform item in trList){
if(item.parent == null)
parentList.Add(item);
else
childsList.Add(item);
}

// Заполняем список
treeData = new Data(null, "Game Objects");

foreach (Transform parent in parentList) {
// Объект не имеющий родителей
Data parentData = new Data(parent, parent.gameObject.name);
treeData.Add(parentData);
// Рекурсивный поиск детей объектов
FindChilds(childsList, parentData);
}
}

void FindChilds(List<Transform> childs, Data parentData){
Transform parent = parentData.tr;
foreach (Transform mayByChild in childs){
if(mayByChild.parent == parent){
// Поиск детей у детей
Data childData = new Data(mayByChild, mayByChild.gameObject.name);
parentData.Add(childData);
FindChilds(childs, childData);
}
}
}
bool isCopyText;
StringBuilder GetTextInfo(){
StringBuilder sb = new StringBuilder();
isCopyText = true;

Object[] objects = FindObjectsOfType(typeof(GameObject));

trList = new List<Transform>();
foreach (Object item in objects) trList.Add((item as GameObject).transform);

//Собрать объекты у которых нет родителей и есть родители
List<Transform> parentList = new List<Transform>();
List<Transform> childsList = new List<Transform>();
foreach (Transform item in trList){
if(item.parent == null)
parentList.Add(item);
else
childsList.Add(item);
}
treeData = new Data(null, "Game Objects");
int innerCount = 0;
foreach (Transform parent in parentList) {
// Объект не имеющий родителей
//sb.AppendLine(parent.gameObject.name);
sb.AppendLine(string.Format(" {0}", parent.gameObject.name));
// Рекурсивный поиск детей объектов
innerCount = 0;
FindChildsStringToBuilder(childsList, parent, ref sb, ref innerCount);
}
isCopyText = false;
return sb;
}
#endregion
bool FindChildsStringToBuilder(List<Transform> childs, Transform parent, ref StringBuilder sb, ref int innerCount){
int firstInnerCount = innerCount;
bool someFind = false;
innerCount++;
string empty = string.Empty;
for (int i = 0; i < innerCount; i++) empty += " ";
foreach (Transform mayByChild in childs){
if(mayByChild.parent == parent){
// Поиск детей у детей
sb.Append(string.Format(" {0}|_{1}", empty, mayByChild.gameObject.name));
FindComponentsStringToBuilder(mayByChild, ref sb);
FindChildsStringToBuilder(childs, mayByChild, ref sb, ref innerCount);
someFind = true;
}
}
innerCount = firstInnerCount;
return someFind;
}

void FindComponentsStringToBuilder(Transform parent, ref StringBuilder sb){
sb.Append(" (");
Component[] comps = parent.GetComponents(typeof(Component));
foreach (Component item in comps) {
sb.Append(item.ToString());
sb.Append(", ");
}
sb.AppendLine(" )");
}
}

В архиве полный текстовый лог из буфера обмена

Hierarchy Lifeless.rar

Как это все можно использовать?

Пока собственно пользы никакой. Только просмотреть какие связи между объектами, компонентами. Роль объектов и компонентов можно предположить по названию. Стандартные компоненты можно увидеть на официальном сайте движка.

В будущем можно сделать так. Выделив объект камера может к нему подлететь и можно этот объект рассмотреть в полете. Так можно исследовать всю игровую сцену. Она вроде там большая и бегать по ней замучаешься. Так что исследовать все лазейки можно этим способом....

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

Cheat.rar

Ссылка на комментарий
Поделиться на другие сайты

post-3-0-58154600-1402504542_thumb.jpg

...

Вопрос глупый... но сталкивался я часто... как вы находите координаты игрока?

Допустим автор темы нашел координату X... Как?

Как он нашел где 0? Где он нашел, что если идти в право X прибавляется, а не уменьшается?

Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.