Skip to content

Instantly share code, notes, and snippets.

@nickludlam
Created August 11, 2021 18:16
Show Gist options
  • Save nickludlam/795a7f147e97f90455885c51fd184f23 to your computer and use it in GitHub Desktop.
Save nickludlam/795a7f147e97f90455885c51fd184f23 to your computer and use it in GitHub Desktop.
How to change Unity meta script references from a DLL to individual files
require 'tempfile'
require 'fileutils'
puts ARGV.inspect
base_path = "unity-project"
file_suffixes = ["*.unity", "*.prefab", "*.controller", "*.mat"]
$unity_loose_file_id = "11500000" # unity hardcoded value
source_data = """
Asset: AbstractMemberBinding,InstanceID: 11912,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -186702827
Asset: AbstractTemplateSelector,InstanceID: 11914,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -1283446872
Asset: AdapterOptions,InstanceID: 11916,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -855988391
Asset: AnimatorParameterBinding,InstanceID: 11918,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -945915645
Asset: BoolToColorAdapterOptions,InstanceID: 11920,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -343842708
Asset: BoolToColorBlockAdapterOptions,InstanceID: 11922,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -150226926
Asset: BoolToStringAdapterOptions,InstanceID: 11924,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: 2072353759
Asset: CollectionBinding,InstanceID: 11926,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: 1223786303,ReplacementGUID: fc8f6e4a5f0376443b6e8516f9aa1cc1
Asset: ColorToColorBlockAdapterOptions,InstanceID: 11928,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -970752098
Asset: DateTimeToStringAdapterOptions,InstanceID: 11930,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -1789889822
Asset: DropdownBinding,InstanceID: 11932,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: 822021643, ReplacementGUID: 0c001c91b7bb4ad4cbcd38435b06117e
Asset: EventBinding,InstanceID: 11934,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -1360956885,ReplacementGUID: 890ec8e82e868b34a8fce21566d83944
Asset: FloatToStringAdapterOptions,InstanceID: 11936,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: 846165451
Asset: OneWayPropertyBinding,InstanceID: 11938,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -1670825535, ReplacementGUID: fc2d9c62932c0394ba2174cf22af8c74
Asset: StringCultureToDateTimeAdapterOptions,InstanceID: 11940,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: 637168853
Asset: SubViewModelBinding,InstanceID: 11942,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -1830646146
Asset: Template,InstanceID: 11944,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: 526415227
Asset: TemplateBinding,InstanceID: 11946,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -456091253
Asset: ToggleActiveBinding,InstanceID: 11948,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -1613660816, ReplacementGUID: a5affc014ccc9214f91fe6a375b020f9
Asset: TwoWayPropertyBinding,InstanceID: 11950,GUID: 33bb0041ebdea4bb8bad0be557ea70a1,FileID: -1957390036, ReplacementGUID: ff0db41e5d06b3e458e4e720862fa166
"""
class UnityScriptReference
attr_accessor :name, :instance_id, :guid, :file_id, :replacement_guid
def initialize(name, instance_id, guid, file_id, replacement_guid)
@name = name
@instance_id = instance_id
@guid = guid
@file_id = file_id
@replacement_guid = replacement_guid
end
def to_s
return "USR: name=#{name} / instance_id=#{instance_id} / guid=#{guid} / file_id=#{file_id} / replacement_guid=#{replacement_guid}"
end
end
$script_references_dict = {}
source_data.split(/\n/).each do |data_line|
dict = {}
data_line.split(",").each do |element|
key, value = element.split(":")
key.strip!
value.strip!
#puts "'#{key}' -> '#{value}'"
dict[key] = value
end
if dict["Asset"]
usr = UnityScriptReference.new(dict["Asset"], dict["InstanceID"], dict["GUID"], dict["FileID"], dict["ReplacementGUID"])
#puts "Created #{usr}"
if $script_references_dict.has_key?(usr.guid)
#puts "Extending #{usr.guid}"
script_references = $script_references_dict[usr.guid]
script_references << usr
$script_references_dict[usr.guid] = script_references
else
#puts "Seeding #{usr.guid}"
$script_references_dict[usr.guid] = [usr]
end
end
end
puts "$script_references_dict"
$script_references_dict.keys.each do |key|
usrs = $script_references_dict[key]
usrs.each do |usr|
puts "#{key} -> #{usr}"
end
end
def file_edit(source_file_path, line_replacements)
file_basename = File.basename(source_file_path)
puts "Rewriting #{source_file_path}"
tmpfile = Tempfile.new(file_basename)
begin
input_line_number = 0
File.readlines(source_file_path).each do |line|
replacement_usr = line_replacements[input_line_number]
if replacement_usr
#puts "RAW_LINE: #{line}"
matches = line.match(/fileID: (-?[\d]+), guid: ([a-z0-9]+), type: ([\d]+)/)
file_ref_fileid = matches[1].strip
file_ref_guid = matches[2].strip
file_ref_type = matches[3].strip
#puts("Replacing guid #{file_ref_guid} with #{replacement_usr.replacement_guid}")
line = line.gsub(file_ref_guid, replacement_usr.replacement_guid)
line = line.gsub(file_ref_fileid, $unity_loose_file_id)
#puts "EDITED_LINE: #{line}"
end
tmpfile << line
input_line_number += 1
end
ensure
tmpfile.close
FileUtils.copy(tmpfile.path, source_file_path)
tmpfile.unlink # deletes the temp file
end
end
file_suffixes.each do |suffix|
glob_path = File.join(base_path, "**", suffix)
Dir.glob(glob_path).each do |f|
#puts "File: #{f}"
line_number = 0
line_replacements = {}
if !File.file?(f)
puts "Skipping non-file #{f}"
continue
end
File.readlines(f).each do |line|
line.strip!
if line =~ /m\_Script/
#puts "found m_Script in #{f}"
#puts line
# Match e.g. " m_Script: {fileID: 11500000, guid: 10801da39a3e6457b83c39f229dd5114, type: 3}"
matches = line.match(/fileID: (-?[\d]+), guid: ([a-z0-9]+), type: ([\d]+)/)
if matches && matches.length == 4
file_ref_fileid = matches[1].strip
file_ref_guid = matches[2].strip
file_ref_type = matches[3].strip
#puts "#{f} contains guid: #{file_ref_guid}"
script_refs = $script_references_dict[file_ref_guid]
if script_refs
script_refs.each do |usr|
if file_ref_fileid == usr.file_id && file_ref_guid == usr.guid
puts "#{f}[#{line_number}] MATCHES #{usr.name}"
puts line
line_replacements[line_number] = usr
end
end
end
else
puts "Problem with regexp!"
exit(1)
end
end
line_number += 1
end
if line_replacements.keys.count > 0
file_edit(f, line_replacements)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment