Prefab は、大元のほうの名前を変えても、シーンに配置されているほうの Prefab の名前は変わりません
Revert したくても、それらしいメニューは無い……。
と思いきや、Inspector を Debug モードに切り替えたらできました。
ただ、何か別の変更を Apply した時点で再び名前が変わらなくなってしまうので、あまり意味はないかもです😥
Prefab は、大元のほうの名前を変えても、シーンに配置されているほうの Prefab の名前は変わりません
Revert したくても、それらしいメニューは無い……。
と思いきや、Inspector を Debug モードに切り替えたらできました。
ただ、何か別の変更を Apply した時点で再び名前が変わらなくなってしまうので、あまり意味はないかもです😥
using Unity.Linq; using UnityEditor; using UnityEngine; using UnityEngine.SceneManagement; public class AllPrefabEdit { [MenuItem("Tools/Edit/Revert All Prefab Instances %F1")] public static void RevertAllPrefabInstances() { foreach (var rootObj in SceneManager.GetActiveScene().GetRootGameObjects()) { foreach (var obj in rootObj.DescendantsAndSelf()) { if (PrefabUtility.IsAnyPrefabInstanceRoot(obj)) { PrefabUtility.RevertPrefabInstance(obj, InteractionMode.AutomatedAction); Debug.Log($"Revert succeeded: {obj.name}"); } } } } [MenuItem("Tools/Edit/Apply All Prefab Instances %F2")] public static void ApplyAllPrefabInstances() { foreach (var rootObj in SceneManager.GetActiveScene().GetRootGameObjects()) { foreach (var obj in rootObj.DescendantsAndSelf()) { if (PrefabUtility.IsAnyPrefabInstanceRoot(obj)) { PrefabUtility.ApplyPrefabInstance(obj, InteractionMode.AutomatedAction); Debug.Log($"Apply succeeded: {obj.name}"); } } } } }
メニューの Tools > Edit か、Ctrl+F1, Ctrl+F2 で実行できます。
※ LINQ to GameObject が必要です。
UniRx を使っていて、複数の ReactiveProperty をまとめて監視して何か処理を行いたいときがたまにあります。
例えば、「デバッグモードが ON」かつ「ミュート設定が ON」になったときのみ音声をミュートする、とか。
デバッグモードとミュート設定をそれぞれ BoolReactiveProperty で持ち、どちらかの値が変わったらミュート状態を切り替える、という実装を考えます。
とりあえず、何も考えずそのままベタ書きしたのが以下のコードです。
public BoolReactiveProperty debugMode; public BoolReactiveProperty muteAllSounds; public AudioSource audioSource; void Start() { debugMode.Subscribe(x => ToggleMute()); muteAllSounds.Subscribe(x => ToggleMute()); } void ToggleMute() { audioSource = debugMode.Value && muteAllSounds.Value; }
そのままだ。そのままですが、だいぶ頭の悪いコードですね……。
せっかく ReactiveProperty を使っているのに、流れてきた値 (x
) を使っていないあたりに頭の悪さが滲み出ています。
「ストリームは合成できる」ということを知っていれば、先程のコードは以下のように書き換えることができます。
public BoolReactiveProperty debugMode; public BoolReactiveProperty muteAllSounds; public AudioSource audioSource; void Start() { Observable.Merge(debugMode, muteAllSounds) .Subscribe(x => ToggleMute()); } void ToggleMute() { audioSource = debugMode.Value && muteAllSounds.Value; }
10 点だったのが、20 点くらいにはなったかな……。
しかしこのやり方だと、流れてくるx
の値がdebugMode
のものなのかmuteAllSounds
のものなのか判らないので、やっぱり使えないままです。
ストリームを Merge で合成すると、debugMode
の値が変わった時にはdebugMode
の値のみが、muteAllSounds
の値が変わった時にはmuteAllSounds
の値のみが流れて来るので、良くなかった、と。
なら、debugMode
の値が変わろうとmuteAllSounds
の値が変わろうと、両方の値が流れてくるようになれば良いわけです。
そのようにしたのがこちら。
public BoolReactiveProperty debugMode; public BoolReactiveProperty muteAllSounds; public AudioSource audioSource; void Start() { Observable.CombineLatest(debugMode, muteAllSounds) .Subscribe(list => { audioSource = list.All(x => x); }); }
だいぶ賢いコードになりましたね!
ストリームを CombineLatest で合成すると、どれかの値が変わったら全部の値が List にまとめられて流れてくるので、「list 内の全要素が true だったら*1ミュート」とすれば、やりたいことが実現できるというわけ。
先程、CombineLatest の説明で「どれかの値が変わったら全部の値が List にまとめられて流れてくる」と書きましたが、これは微妙に違くて、すべてのストリームに一回以上値が流れていないと List は流れてきません。
それなのになぜ上記のコードが valid なのかというと、ReactiveProperty は値が変化した時だけでなく Subscribe した瞬間にもその時点での値が一回流れるので、自動的に「一回以上値が流れている」が満たされるからですね。
参考:
neue cc - Unityにおけるコルーチンの省メモリと高速化について、或いはUniRx 5.3.0でのその反映
(UniRxの)ReactivePropertyはSubscribe時に必ず値をプッシュするようになってる
*1:list.All(x => x) の部分。
ある日のこと。
DOTween を使っていたら、特に動作に問題はないけどなぜか警告を吐いてきました。
DOTWEEN ► This Tween has been killed and is now invalid
「あなたが操作しようとしたトゥイーンはすでに無効になってますよ~」とのこと。
該当のコードはこんな感じ:
if (tweener != null && tweener.IsPlaying()) { tweener.Complete(); }
トゥイーンが再生中だったら即完了にするよっていう処理です。
何の変哲もないコードだと思うけどなぁ……。null チェックもちゃんとしてるし、何がいけないんだろう🤔
似たようなメソッドを並べてみて、片っ端から調べてみました(雑……!)。
if (tweener != null) { Debug.Log(tweener.fullPosition); Debug.Log(tweener.CompletedLoops()); Debug.Log(tweener.Delay()); Debug.Log(tweener.Duration()); Debug.Log(tweener.Elapsed()); Debug.Log(tweener.ElapsedDirectionalPercentage()); Debug.Log(tweener.ElapsedPercentage()); Debug.Log(tweener.IsActive()); Debug.Log(tweener.IsBackwards()); Debug.Log(tweener.IsComplete()); Debug.Log(tweener.IsInitialized()); Debug.Log(tweener.IsPlaying()); Debug.Log(tweener.Loops()); }
上記のコードを実行してみたところ、なんとtweener.IsActive()
のみ警告が発生しないという結果に! どうやら、再生し終わったトゥイーンに対しては、有効かどうか以外を調べるのは非推奨のようです。tweener.IsPlaying()
と書けば一応 false を返してくれるけど、そもそも tweener 自体がもう無効になっているからそんなこと聞いてくるな、ということか。
ということで、以下のように書き換えると、無事警告は出なくなりました。*1
if (tweener != null && tweener.IsActive() && tweener.IsPlaying()) { tweener.Complete(); }
*1:この if 文中の tweener.IsPlaying() が警告されないのは、直前の tweener.IsActive() が false だったらその時点で式の評価が終了するからですね(短絡評価)。
表題のとおりです。
哀しい😢
Simple usage — openpyxl 3.0.3 documentation
Warning
openpyxl does currently not read all possible items in an Excel file so images and charts will be lost from existing files if they are opened and saved with the same name.
ライブラリを使うときはちゃんと公式を読もう!(戒め)
一応スクリプトも置いておきます。
################################################################################ # Excel ファイルを扱うテストです。 ################################################################################ import glob import openpyxl import os # 作業ディレクトリのパス WORKING_DIRECTORY_PATH = os.path.dirname(os.path.abspath(__file__)) # 作業ディレクトリと同階層にあるすべての xlsx ファイルに対して処理を行う for xlsx_file in glob.glob(f"{WORKING_DIRECTORY_PATH}\\*.xlsx", recursive=True): # xlsx ファイルをロード book = openpyxl.load_workbook(xlsx_file) print(f"{xlsx_file} loaded.") # 処理 # xlsx ファイルをセーブ book.save(xlsx_file) print(f"{xlsx_file} saved.")
最近は Visual Studio Code でも C# が動くんですね!
Visual Studio なんていらんかったんや!
ということで、公式チュートリアルの通りにやってみたところ……。
本来ならアプリのビルドとデバッグに必要なアセットの追加を求められるべきところで、なにやら怪しげな警告が。
恐る恐る内容を開いてみると……。
[info]: OmniSharp.Stdio.Host Starting OmniSharp on Windows 6.2.9200.0 (x64) [info]: OmniSharp.Services.DotNetCliService DotNetPath set to dotnet [info]: OmniSharp.MSBuild.Discovery.MSBuildLocator Located 2 MSBuild instance(s) 1: Visual Studio Community 2017 15.8.28010.2048 - "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin" 2: StandAlone 15.0 - "C:\Users\Gigacee\.vscode\extensions\ms-vscode.csharp-1.17.1\.omnisharp\1.32.8\msbuild\15.0\Bin" [info]: OmniSharp.MSBuild.Discovery.MSBuildLocator Registered MSBuild instance: Visual Studio Community 2017 15.8.28010.2048 - "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin" // 中略 [fail]: OmniSharp.MSBuild.ProjectManager Attemped to update project that is not loaded: c:\Users\Gigacee\Sandbox\dotnet\Hello World.csproj
どうやら、 Visual Studio Code の C# 拡張ではなく、 Visual Studio Community 2017 の MSBuild を呼んでしまってエラーが起こっているようです。
Visual Studio をアンインストールしてしまえば解決しそうですが、 Unity でゲーム開発をするときとかにまだ使うんですよね……。
(さっき「いらんかったんや!」と言ったばかりですが……)
なんとか Visual Studio を生かしたまま解決できないかと色々試した結果、 Visual Studio 自体に .NET Core をインストールすることでうまくいきました。
Visual Studio Installer を起動し、「変更」から、「.NET Core クロスプラットフォームの開発」をインストールすれば OK !
なんで自分自身の MSBuild より外部の MSBuild の方が優先されるんですかね……謎です。
問題自体は認識されているようです。
早く直ると良いですね。
The coloring of this site is Dracula PRO🧛🏻♂️
This website uses the FontAwesome icons licensed under CC BY 4.0.
2020 GIGA CREATION