import argparse import json import random from pathlib import Path UNITY_EXAMPLES = [ { "instruction": "Unity'de WASD ile CharacterController kullanan FPS hareket kodu yaz.", "answer": """Bu script Player objesine eklenir. Objede `CharacterController` component'i olmalı. ```csharp using UnityEngine; [RequireComponent(typeof(CharacterController))] public class PlayerMovement : MonoBehaviour { [SerializeField] private float speed = 5f; [SerializeField] private float gravity = -9.81f; private CharacterController controller; private Vector3 velocity; private void Awake() { controller = GetComponent(); } private void Update() { float x = Input.GetAxisRaw("Horizontal"); float z = Input.GetAxisRaw("Vertical"); Vector3 move = transform.right * x + transform.forward * z; controller.Move(move.normalized * speed * Time.deltaTime); if (controller.isGrounded && velocity.y < 0f) velocity.y = -2f; velocity.y += gravity * Time.deltaTime; controller.Move(velocity * Time.deltaTime); } } ``` Yeni Input System kullanıyorsan `Input.GetAxisRaw` yerine input action callback'leriyle vektör okuyabilirsin.""", }, { "instruction": "Unity 2D'de Rigidbody2D ile oyuncu hareketi yaz.", "answer": """Bu örnek top-down 2D hareket içindir. Player objesinde `Rigidbody2D` olmalı ve gravity scale genelde 0 yapılır. ```csharp using UnityEngine; [RequireComponent(typeof(Rigidbody2D))] public class PlayerMovement2D : MonoBehaviour { [SerializeField] private float speed = 6f; private Rigidbody2D rb; private Vector2 input; private void Awake() { rb = GetComponent(); } private void Update() { input.x = Input.GetAxisRaw("Horizontal"); input.y = Input.GetAxisRaw("Vertical"); input = input.normalized; } private void FixedUpdate() { rb.linearVelocity = input * speed; } } ``` Eski Unity sürümlerinde `linearVelocity` yerine `velocity` kullanılır.""", }, { "instruction": "Unity'de coin toplama sistemi C# ile nasıl yapılır?", "answer": """Coin objesinde trigger collider olmalı. Player objesini tag veya component ile ayırt edebilirsin. ```csharp using UnityEngine; public class Coin : MonoBehaviour { [SerializeField] private int value = 1; private void OnTriggerEnter(Collider other) { if (!other.TryGetComponent(out var wallet)) return; wallet.AddCoins(value); Destroy(gameObject); } } public class PlayerWallet : MonoBehaviour { public int Coins { get; private set; } public void AddCoins(int amount) { Coins += amount; } } ```""", }, { "instruction": "Unity'de Health component yaz.", "answer": """Health'i ayrı component yapmak Player, enemy ve kırılabilir objelerde yeniden kullanımı kolaylaştırır. ```csharp using System; using UnityEngine; public class Health : MonoBehaviour { [SerializeField] private int maxHealth = 100; public int Current { get; private set; } public event Action Changed; public event Action Died; private void Awake() { Current = maxHealth; } public void TakeDamage(int amount) { Current = Mathf.Max(Current - amount, 0); Changed?.Invoke(Current, maxHealth); if (Current == 0) Died?.Invoke(); } } ```""", }, { "instruction": "Unity'de ScriptableObject ile item tanımı nasıl yapılır?", "answer": """ScriptableObject, item verisini prefab veya sahne bağımlılığı olmadan saklamak için uygundur. ```csharp using UnityEngine; [CreateAssetMenu(menuName = "Game/Item")] public class ItemDefinition : ScriptableObject { public string id; public string displayName; public Sprite icon; public int maxStack = 1; } ``` Project penceresinde sağ tıklayıp `Create > Game > Item` ile asset oluşturabilirsin. Runtime state'i ScriptableObject üzerinde değil, inventory component içinde tutulmalıdır.""", }, { "instruction": "Unity'de null reference exception nasıl debug edilir?", "answer": """`NullReferenceException`, null olan bir değişkenin alanına veya metoduna eriştiğini gösterir. Inspector referansı atanmış mı, `GetComponent` sonucu null mı ve obje sahnede aktif mi kontrol et. ```csharp [SerializeField] private Transform target; private void Awake() { if (target == null) { Debug.LogError("Target referansı Inspector'dan atanmadı.", this); enabled = false; return; } } ``` Hata satırına çift tıkla, o satırdaki her referansı tek tek kontrol et.""", }, ] UNREAL_EXAMPLES = [ { "instruction": "Unreal Engine C++ ile basit Character hareket sınıfı yaz.", "answer": """Enhanced Input kurulu projelerde input binding genelde Character içinde yapılır. Aşağıdaki iskelet hareket fonksiyonlarını gösterir. ```cpp // MyPlayerCharacter.h #pragma once #include "CoreMinimal.h" #include "GameFramework/Character.h" #include "MyPlayerCharacter.generated.h" UCLASS() class AMyPlayerCharacter : public ACharacter { GENERATED_BODY() public: AMyPlayerCharacter(); protected: virtual void SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) override; void MoveForward(float Value); void MoveRight(float Value); }; ``` ```cpp // MyPlayerCharacter.cpp #include "MyPlayerCharacter.h" AMyPlayerCharacter::AMyPlayerCharacter() { PrimaryActorTick.bCanEverTick = true; } void AMyPlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent) { Super::SetupPlayerInputComponent(PlayerInputComponent); PlayerInputComponent->BindAxis("MoveForward", this, &AMyPlayerCharacter::MoveForward); PlayerInputComponent->BindAxis("MoveRight", this, &AMyPlayerCharacter::MoveRight); } void AMyPlayerCharacter::MoveForward(float Value) { AddMovementInput(GetActorForwardVector(), Value); } void AMyPlayerCharacter::MoveRight(float Value) { AddMovementInput(GetActorRightVector(), Value); } ```""", }, { "instruction": "Unreal C++ ile Actor içinde rotating pickup yaz.", "answer": """Pickup için `AActor` türetip mesh'i root'a bağlayabilir ve Tick içinde döndürebilirsin. ```cpp UCLASS() class ARotatingPickup : public AActor { GENERATED_BODY() public: ARotatingPickup(); virtual void Tick(float DeltaSeconds) override; protected: UPROPERTY(VisibleAnywhere) UStaticMeshComponent* Mesh; UPROPERTY(EditAnywhere, Category="Pickup") float RotationSpeed = 90.0f; }; ``` ```cpp ARotatingPickup::ARotatingPickup() { PrimaryActorTick.bCanEverTick = true; Mesh = CreateDefaultSubobject(TEXT("Mesh")); RootComponent = Mesh; } void ARotatingPickup::Tick(float DeltaSeconds) { Super::Tick(DeltaSeconds); AddActorLocalRotation(FRotator(0.0f, RotationSpeed * DeltaSeconds, 0.0f)); } ```""", }, { "instruction": "Unreal Engine'de UPROPERTY ve UFUNCTION ne işe yarar?", "answer": """`UPROPERTY`, değişkeni Unreal reflection sistemine tanıtır. Böylece garbage collector, Blueprint, editor ve serialization sistemi değişkeni görebilir. `UFUNCTION`, C++ fonksiyonunu reflection sistemine açar. Blueprint'ten çağırmak veya event olarak kullanmak için gerekir. ```cpp UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Stats") float MaxHealth = 100.0f; UFUNCTION(BlueprintCallable, Category="Stats") void TakeDamageAmount(float Amount); ``` Unreal'da UObject referanslarını çoğu zaman `UPROPERTY` ile tutmak önemlidir; aksi halde GC davranışı sorun çıkarabilir.""", }, { "instruction": "Unreal C++ ile Health component yaz.", "answer": """Reusable health için `UActorComponent` uygundur. ```cpp UCLASS(ClassGroup=(Custom), meta=(BlueprintSpawnableComponent)) class UHealthComponent : public UActorComponent { GENERATED_BODY() public: UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Health") float MaxHealth = 100.0f; UPROPERTY(BlueprintReadOnly, Category="Health") float CurrentHealth = 100.0f; UFUNCTION(BlueprintCallable, Category="Health") void ApplyDamage(float Amount) { CurrentHealth = FMath::Clamp(CurrentHealth - Amount, 0.0f, MaxHealth); if (CurrentHealth <= 0.0f) { // Death event veya BlueprintImplementableEvent çağrılabilir. } } }; ``` Daha gelişmiş sürümde multicast delegate ile UI ve gameplay sistemlerine haber verilir.""", }, { "instruction": "Unreal Blueprint ile kapı açma mantığını anlat.", "answer": """Kapı actor'ünde `Box Collision`, kapı mesh'i ve timeline bulunur. Player overlap olduğunda timeline çalışır, timeline değeriyle kapının rotation veya location değeri interpolate edilir. Akış: - `OnComponentBeginOverlap` tetiklenir. - Overlap eden actor player mı kontrol edilir. - Timeline `Play` çağrılır. - Timeline update pin'inde `SetRelativeRotation` veya `SetRelativeLocation` kullanılır. - Çıkışta `OnComponentEndOverlap` ile timeline reverse yapılabilir. C++ gerekiyorsa aynı mantık `UBoxComponent` ve `FTimeline` ile kurulabilir.""", }, { "instruction": "Unreal C++ derleme hatalarında nasıl debug yapılır?", "answer": """Önce derleyicinin verdiği ilk hataya bak. Unreal build çıktısında sonraki hatalar çoğu zaman ilk hatanın sonucudur. Kontrol listesi: - Header dosyasında `GENERATED_BODY()` doğru yerde mi? - `.generated.h` include'u en son include mu? - Sınıf adı dosya ve constructor adıyla uyumlu mu? - Eksik module dependency var mı? - Pointer tipleri forward declaration ile yetiyor mu, yoksa include gerekli mi? Reflection hatalarında Unreal Editor'ü kapatıp temiz build almak da gerekebilir.""", }, ] UNITY_PROMPTS = [ "Unity için basit player movement yaz.", "Unity C# ile karakter hareketi örneği ver.", "MonoBehaviour içinde WASD movement nasıl yazılır?", "Unity'de oyuncu hareket kodunu temiz şekilde göster.", ] UNREAL_PROMPTS = [ "Unreal C++ ile basit player movement yaz.", "Unreal Engine Character class içinde hareket input'u bağla.", "UE C++ AddMovementInput örneği ver.", "Unreal'da Character hareket kodunu temiz şekilde göster.", ] UNREAL_HEALTH_PROMPTS = [ "Unreal C++ ile Health component yaz.", "UE C++ UActorComponent tabanlı health component örneği ver.", "Unreal Engine'de can sistemi için UHealthComponent yaz.", "Unreal'da BlueprintCallable TakeDamage fonksiyonu olan health component oluştur.", ] def add_variants(rows, domain, prompts, answer): for prompt in prompts: rows.append({"domain": domain, "instruction": prompt, "answer": answer}) def build_rows(seed): random.seed(seed) rows = [] for item in UNITY_EXAMPLES: rows.append({"domain": "unity", **item}) for item in UNREAL_EXAMPLES: rows.append({"domain": "unreal", **item}) add_variants(rows, "unity", UNITY_PROMPTS, UNITY_EXAMPLES[0]["answer"]) add_variants(rows, "unreal", UNREAL_PROMPTS, UNREAL_EXAMPLES[0]["answer"]) add_variants(rows, "unreal", UNREAL_HEALTH_PROMPTS, UNREAL_EXAMPLES[3]["answer"]) for _ in range(6): rows.append({"domain": "unreal", **UNREAL_EXAMPLES[3]}) rows.append({"domain": "unity", **UNITY_EXAMPLES[3]}) rows.append({"domain": "unity", **UNITY_EXAMPLES[0]}) rows.append({"domain": "unreal", **UNREAL_EXAMPLES[0]}) prefixes = [ "Kısa açıkla:", "Yeni başlayan biri için anlat:", "Kod örneğiyle göster:", "Hata ayıklama açısından açıkla:", "En temiz mimariyle öner:", ] base_rows = list(rows) for prefix in prefixes: for item in base_rows: rows.append( { "domain": item["domain"], "instruction": f"{prefix} {item['instruction']}", "answer": item["answer"], } ) # Extra weight helps the small model keep engine-specific syntax separated. rows = rows * 3 random.shuffle(rows) return rows def main(): parser = argparse.ArgumentParser() parser.add_argument("--out", default="data/instructions/multiengine_v1.jsonl") parser.add_argument("--seed", type=int, default=123) args = parser.parse_args() rows = build_rows(args.seed) out = Path(args.out) out.parent.mkdir(parents=True, exist_ok=True) with out.open("w", encoding="utf-8") as f: for row in rows: f.write(json.dumps(row, ensure_ascii=False) + "\n") print(f"wrote {len(rows)} rows to {out}") if __name__ == "__main__": main()