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

Unity3d. Исследование нанесения урона


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

Версия 1.0

Приложение ShotGame.rar
Пакадж (для тех у кого Unity3d 4.0) ShotUnitypackage.rar

post-3-0-97402900-1356862231_thumb.jpg

Пользователь наводит пистолет на стену. После чего выстреливает. Создаётся пуля, ей придаётся сила и пуля летит в стену. Как только пуля касается стены, то стене наносится урон. Количество выстрелов и количество "здоровья" стены отображается в левом верхнем углу. Наша задача исследовать и сделать так чтобы пуля не наносила урон стене.


Содержание:

1. Обзор игры и кода высокого уровня в игровом движке



В объекте пули есть поведение (скрипт BulletCollision.cs). Когда пуля соприкасается с коллизей стены, то происходит анимация пламени (prefabflashAnimation) и стене отправляется событие OnDamage с аргументом power OnCollisionEnter. Это стандартная функция-приёмник оповещающая, что была коллизия.

post-3-0-72710700-1356866149_thumb.jpg



А у стены есть скрипт-поведение Unit.cs, в котором есть функция-приёмник OnDamage.

post-3-0-43354500-1356865851_thumb.jpg


В результате соприкосновения коллизий пули и стены получаем, что через сообщение у стены отнимается "здоровье" (если так можно выразиться, подразумевается "прочность стены"). Конечно, здесь нет условия Game Over, если здоровье будет меньше нуля. Оно нам сейчас не особо важно.


2. Обзор отладочного кода
using UnityEngine;using System.Collections;public class BulletCollision : MonoBehaviour {public GameObject prefabflashAnimation;public float power = 25f;void OnCollisionEnter(Collision collision){GameObject.Instantiate(prefabflashAnimation,collision.contacts[0].point,prefabflashAnimation.transform.rotation);collision.collider.SendMessage("OnDamage", power, SendMessageOptions.DontRequireReceiver);}}
using UnityEngine;using System.Collections;public class Unit : MonoBehaviour {public float health = 1000000f;string strHealth = "<b>Wall Health</b> 1000000";void OnGUI() {GUILayout.Label(strHealth, GUILayout.Width(220f), GUILayout.Height(30f));}void OnDamage(float valueDamage) {health -= valueDamage;strHealth = "<b>Wall Health</b> " + health.ToString();}}

Наша задача сейчас рассмотреть классический метод. Ищем адрес здоровья. Ставим бряк и смотрим код.

post-3-0-17089400-1356867163_thumb.jpg

Хм. Знакомое окно, знакомая картина.

0797AEFB - 57 - push edi
0797AEFC - 83 EC 04 - sub esp,04
0797AEFF - 8B 7D 08 - mov edi,[ebp+08]
0797AF02 - D9 47 14 - fld dword ptr [edi+14] //EDI=00BB4F60
0797AF05 - D9 45 0C - fld dword ptr [ebp+0C]
0797AF08 - DEE9 - fsubp st(1),st(0)
0797AF0A - D9 5F 14 - fstp dword ptr [edi+14]
0797AF0D - 8D 47 14 - lea eax,[edi+14]
0797AF10 - 83 EC 0C - sub esp,0C
0797AF13 - 50 - push eax
0797AF14 - E8 D7000000 - call 0797AFF0 // переход на 3-тий бряк
0797AF19 - 83 C4 10 - add esp,10
0797AF1C - 83 EC 08 - sub esp,08
0797AF1F - 50 - push eax
0797AF20 - 68 E097B900 - push 00B997E0 : [0752132C]
0797AF25 - E8 3E7CFDFF - call 07952B68
0797AF2A - 83 C4 10 - add esp,10
0797AF2D - 89 47 10 - mov [edi+10],eax
0797AF30 - 8D 65 FC - lea esp,[ebp-04]
0797AF33 - 5F - pop edi
0797AF34 - C9 - leave
0797AF35 - C3 - ret


Те кто умеют делать скрипты на CE здесь бы просто могли по сигнатуре нопить fsubp st(1),st(0). Фильтров пока не касаемся. Стена у нас одна, других стен нет.

3. Обзор структур данных

Вспоним что EDI=00BB4F60, а вот структура

post-3-0-64441800-1356868127_thumb.jpg

Особо нам это ничего не говорит. Посмотрим в отладчик Mono

post-3-0-61016600-1356868402_thumb.jpg

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



4. Другой способ

Мы подходим к самому главному. К отключению коллизии.


В редакторе это делается просто снятием галочки
post-3-0-08690000-1356868677_thumb.jpg

И наша задача как эту галочку снять средствами CE. А вот как именно, об этом позже.

Продолжение следует...
Изменено пользователем MasterGH
Ссылка на комментарий
Поделиться на другие сайты

  • 1 год спустя...

Еле нашел файлы и залил в аттач. Надеюсь, за 26 мегайбайт Xipho не будет ругаться.

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

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

Еле нашел файлы и залил в аттач. Надеюсь, за 26 мегайбайт Xipho не будет ругаться.

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

У нас 100 гигов на портале, так что 26 мегов - это мелочь, правда же, да? ))))

ЗЫ. На досуге начал углубленно осваивать "решетки". Посмотрим, что из этого выйдет )

И да, грядет глобальное обновление нашего портала (как только выдастся свободное время).

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

  • 2 недели спустя...

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

Меня только сейчас осенило, что Unity преимущественно C# (Java) движок. А ломать игры, написанные на C#, при помощи Cheat Engine то ещё удовольствие. Там адреса будут постоянно слетать. Проще скрипт, отвечающий за коллизию, из dll выкорчевать и переписать. Надо будет попробовать на досуге...

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

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

Unity3d использует .net сборки для работы своих приложений на разных платформах. Поэтому можно пойти например тремя путями

1. Сделать инъекцию кода в сборку Assembly-CSharp.dll

2. Переписать Assembly-CSharp.dll

3. Отлаживать машинный код

Варианты 1 и 3 делать долго. А вот вариант 2 очень даже простой.

1. Ищем Assembly-CSharp.dll

2. Декомпилируем через ILSpy

3. Находим класс Unit


using System;
using UnityEngine;
public class Unit : MonoBehaviour
{
public float health = 1000000f;
private string strHealth = "<b>Wall Health</b> 1000000";
private void OnGUI()
{
GUILayout.Label(this.strHealth, new GUILayoutOption[]
{
GUILayout.Width(220f),
GUILayout.Height(30f)
});
}
private void OnDamage(float valueDamadge)
{
this.health -= valueDamadge;
this.strHealth = "<b>Wall Health</b> " + this.health.ToString();
}
}

4. В этот класс добавляем функцию, которая бы включала и выключала коллизию. Прочитав документацию по скриптингу на официальном сайте узнали, что это можно сделать в функции Update:


private void Update()
{
//Cheat Disable Wall collision
if(Input.GetKeyUp(KeyCode.H)){
collider.enabled = !collider.enabled;
}
}

Сделать это можно декомпилировав Assembly-CSharp.dll и построив новую .net библиотеку Assembly-CSharp.dll в программе Sharp Develop (бесплатная среда разработки .net)

post-3-0-66601300-1393257871_thumb.png

5.Компилируем проект в Sharp Develop и заменяем файл Assembly-CSharp.dll

6. Запускаем игру и при нажатии на кнопку H можем стрелять сквозь стену. Что собственно я и хотел сделать.

----

Вывод1. Теперь ни по одной стене попасть нельзя (хотя там одна стена). Стрельба происходит насквозь стены. Если бы это был игрок, а не стена, то игрок с классом Unit был бы бессмертным. К сожалению на .net игры тормозные и их под PC мало.

Вывод2. Можно находиться мыслями на более высоком уровне "функций", а не на машинном коде. Иными словами зная функции движка (не только Unity3d, а например UDK) и аргументы функции, можно эти функции использовать для создания читов. Например изменять/читать характеристики коллизий, характеристики игрока... Хотя многие крутые игровые движки и документация SDK закрыты от обычного смертного, все равно можно ковырять и трейсить функции чтобы понять какая функция, что делает. Тогда например посмотрев на каком игровом движке написана игра можно смело использовать сигны функций на любой игре этого движка. Это уже что-то типа сигны на все игры этого движка, а не только на все версии определенной игры...

Assembly-CSharp.rar

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

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

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

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