This article was first published on my personal blog: blog.shenyuanluo.com. Welcome to subscribe if you like.

There are plenty of tutorials online on how to integrate iOS native projects into Unity projects, which I won’t cover here. Here’s how to automate the process of Unity code updates to iOS projects.

In a regular Unity code update, you go through the following steps:

  1. UnityThe code is compiled to generate the correspondingUnity_iOSengineering
  2. theUnity_iOSProject update code (generally:Libraries,Classes,DataUpdate file data for these three directories) to merge into nativeiOSengineering
  3. The nativeiOSProject add corresponding interface processing…

In fact, the second step of merging involves a lot of similar repetitive work. Each time, the code files are deleted and modified. Using BeyondCompare on a regular basis can meet current requirements. However, if you need to update Your Unity code frequently, there is no guarantee that every time you manually compare the code to the files that have been added to it, and it adds to the workload, so you decide to make a script to automate this process.

Unity code update process

Continue to refine the merging steps, which can be divided into the following:

  • New Unity file
  • Delete Unity files
  • Modify Unity files

For these operation requirements, shell can meet these requirements. The general idea is as follows:

Go through Unity project files and iOS project files (mainly the Native subfolders under the Libraries, Data, folders and Classes directories). For new and modified files, you can directly cp them, and record the new files/folders. For deleted files, you can run the Unity project files and iOS project files (mainly the Native subfolders under the Classes directories). You can directly rm and record the deleted files or folders.

So I wrote a script like this:

Find new Unity files (shell)

#Recursively check for 'new' files
#Param1: indicates the source folder. Param2: indicates the destination folderFunction rec_check_add_file() {dir_list =$(ls $1)} for name in ${dir_list[*]}  "$1" == "$source_dir" ] ; Then # top-level folder filter if [" $name "! = "Classes"] && [" $name "! = "Data"] && [" $name "! = "Libraries"]. then continue fi fi if [ "$1" == "$source_dir/Classes" ]; If ["$name"!= "Native"]; then continue fi fi if [ -f $1/$name ]; If [! -f $2/$name]; if [! -f $2/$name]; Add_file_array [${#add_file_array[@]}]=$2/$name $1/$name" cp $1/$name $2/$name # elif [-d $1/$name]; If [! -d $2/$name]; if [! -d $2/$name]; Add_foloder_array [${#add_foloder_array[@]}]=$2/$name [${#add_foloder_array[@]}] Rec_check_add_file $1/$name $2/$name $done}Copy the code

Find Unity delete file (shell)

#Recursively check for 'delete' files
#Param1: indicates the source folder. Param2: indicates the destination folder.Function rec_check_del_file() {dir_list =$(ls $1) # for name in ${dir_list[*]} # do if [-f $1/$name ]; If [! -f $2/$name]; if [! -f $2/$name]; Then # if the path '$2 / $name file does not exist del_file_array [${# del_file_array} [@]] = $2 / $name # records' delete' document#                echo "Delete file:The $1/$name"Rm $1/$name [-d $1/$name]; If [! -d $2/$name]; if [! -d $2/$name]; Rec_check_del_file $1/$name = rec_check_del_file $1/$name = rec_check_del_file $1/$name = rec_check_del_file $1/$name = rec_check_del_file $1/$name = rec_check_del_file $1/$name = rec_check_del_file $1/$name = rec_check_del_file $1/$name = rec_check_del_file $1/$name $2/$name fi fi done }Copy the code

Now that the Unity project and iOS project physical files/folders are handled, it’s time to add/remove file/folder dependencies to the iOS project. At that time, I found that shell could not handle directly (mainly the processing of ***.xcodeProj file, I did not understand the logical relationship), then I found that some great people had gone ahead (I said that there was no mature solution for such a public demand), Xcodeproj: Xcodeproj: Xcodeproj: Xcodeproj: Xcodeproj: Xcodeproj: Xcodeproj: Xcodeproj: Xcodeproj

IOS project file dependencies added

With Xcodeproj, command line management of Xcode file dependencies is exceptionally convenient; However, the physical file relationship was handled in shell and the dependency relationship was handled in Ruby, two different scripting languages. Although both can be mixed with each other, but for me who is not very familiar with scripts, it is more difficult, simply write a set of physical file processing scripts in Ruby.

Find new Unity files (Ruby)

Recursively check for 'new' files
def rec_check_add_file(src_file_path, dest_file_path)
    Dir.foreach(src_file_path) do |file_name|
        # System 'hides' file filtering
        if file_name == "." or file_name == ".." or file_name == ".DS_Store"
            next
        end
        # resource folder filtering
        if src_file_path == @source_dir_path    # top-level folder filtering
            iffile_name ! ="Classes" andfile_name ! ="Data" andfile_name ! ="Libraries"
                next
            end
        end
        # Classes/Native folder filtering
        if src_file_path == @source_dir_path + "/Classes"
            iffile_name ! ="Native"
                next
            end
        end

        if File.directory? (src_file_path + "/" + file_name)  # if 'folder'
            unless File.exist? (dest_file_path + "/" + file_name)   # If the folder does not exist
                @add_foloder_array.push(dest_file_path + "/" + file_name)   # Record the 'new' folder
                Dir.mkdir(dest_file_path + "/" + file_name) Create folder
            end
            # Recursive processing
            rec_check_add_file(src_file_path + "/" + file_name, dest_file_path + "/" + file_name)
        elsif File.file? (src_file_path + "/" + file_name)    # if 'file'
            unless File.exist? (dest_file_path + "/" + file_name) The file does not exist
                @add_file_array.push(dest_file_path + "/" + file_name)  # Record 'new' files
            end
            FileUtils.cp(src_file_path + "/" + file_name, dest_file_path + "/" + file_name) Copy to target path
        end
    end
end
Copy the code

Find Unity delete files (Ruby)

# Recursively check for 'delete' files
def rec_check_del_file(src_file_path, dest_file_path)
    Dir.foreach(src_file_path) do |file_name|
        # System 'hides' file filtering
        if file_name == "." or file_name == ".." or file_name == ".DS_Store"
            next
        end

        if File.directory? (src_file_path + "/" + file_name)  # if 'folder'
            if File.exist? (dest_file_path + "/" + file_name)   If the folder exists
                # Recursive processing
                rec_check_del_file(src_file_path + "/" + file_name, dest_file_path + "/" + file_name)
            else
                rec_delete_file(src_file_path + "/" + file_name)   # then recursively delete the files under the folder
            end
        elsif File.file? (src_file_path + "/" + file_name)    # if 'file'
            unless File.exist? (dest_file_path + "/" + file_name) The file does not exist
                @del_file_array.push(src_file_path + "/" + file_name)  # Record 'delete' file
                File.delete(src_file_path + "/" + file_name)   Delete the source file
            end
        end
    end
end
Copy the code

Add Unity file dependencies (Ruby)

Add file dependencies
def add_reference(target, project, to_group, file_path, need_mrc)
    if to_group andFile::exist? (file_path)iffile_path ! ="." andfile_path ! =".." andfile_path ! =".DS_Store"
            pb_gen_file_path = file_path
            if to_group.find_file_by_path(pb_gen_file_path)
                puts pb_gen_file_path + " reference exist"
            else
                file_reference = to_group.new_reference(pb_gen_file_path)
                if need_mrc and file_path.include? ("pbobjc.m")
                    target.add_file_references([file_reference],'-fno-objc-arc')
                else
                    target.add_file_references([file_reference])
                end
            end
        end
        project.save
    end
end
Copy the code

Remove Unity file dependencies (Ruby)

# Remove file dependencies
def rmv_reference(target, project, from_group, file_path)
    if from_group and file_path
        from_group.files.each do |file_ref|
            if file_ref.real_path.to_s == file_path
                file_ref.remove_from_project
                target.source_build_phase.remove_file_reference(file_ref)
                target.resources_build_phase.remove_file_reference(file_ref)
                target.headers_build_phase.remove_file_reference(file_ref)
                break
            end
        end
        project.save
    end
end
Copy the code

Unity code update automation is now complete!

I found that Ruby is much faster than shell in processing physical files. Shell takes 4-5 seconds to process the same engineering code file, while Ruby only takes 1-2 seconds. I remember shell commands being fast, but how come Ruby is faster than shell? If you know the big guy, but also hope to inform, thanks!

supplement

To add/remove file dependencies, you need to install the Ruby library Xcodeproj. If not, you need to install it

sudo gem install xcodeproj

Full script

The Ruby script file can be downloaded here

reference

  1. Lazy bonus: Modify Xcode projects with scripts
  2. Add files to the Xcode project using code
  3. Ruby operation project. Xcodeproj