Bu bölümde, burada Unreal Engine ile geliştirdiğimiz projeye etkileşim (interaction) işlemleri eklemeye çalışacağız.
Unreal Engine'de bir etkileşim sistemi, oyuncunun dünyadaki nesnelerle iletişim kurmasını sağlayan temel bir mekaniktir. Bu sistem, kapı açmaktan, eşya toplamaya veya bir NPC ile konuşmaya kadar birçok farklı eylem için kullanılabilir.
Temel olarak bir etkileşim sistemi şu üç ana unsurdan oluşur:
- Etkileşebilir nesneler
- Oyuncu arayüzü (HUD)
- Oyuncunun etkileşim yeteneği
NPC, Non-Player Character (Oyuncu Olmayan Karakter) anlamına gelir. Bu terim, bir video oyununda oyuncu tarafından kontrol edilmeyen tüm karakterleri tanımlamak için kullanılır. Bu karakterler, genellikle oyunun hikayesine katkıda bulunan, görevler veren veya oyun dünyasını daha canlı hale getiren roller üstlenirler.
1. Etkileşebilir nesneler (Interactable Actors)
Bir nesnenin etkileşime girmesi için onu özel bir sınıf veya arayüz (interface) ile işaretlemek gerekir. Unreal Engine'de bu genellikle bir Blueprint Interface kullanarak yapılır.
Blueprint Interface: Bir Blueprint Interface, nesnelerin sahip olması gereken ortak fonksiyonları tanımlar. Örneğin, Interact adlı bir fonksiyon tanımlarsınız. Bu arayüzü uygulayan her Blueprint (örneğin bir kapı, bir sandık veya bir anahtar) bu fonksiyonu kendi içinde farklı şekillerde (kapıyı açma, sandığı açma, anahtarı envantere ekleme) uygulayabilir. Bu yaklaşım, kodun daha temiz ve düzenli olmasını sağlar.
2. Oyuncunun etkileşim yeteneği
Oyuncunun bir nesneyle etkileşime girmesi için öncelikle o nesneyi algılaması ve tetiklemesi gerekir.
Algılama (Detection)
Oyuncunun görüş hattı (Line trace ve Sphere trace) veya çevresindeki bir etkileşim alanı (örneğin, bir küre veya kutu şeklinde bir collision box) kullanılarak nesneler algılanır. Line Trace ve Sphere Trace, Unreal Engine'de nesnelerin fiziksel dünyada birbirini algılaması için kullanılan temel ışın döküm (ray casting) yöntemleridir. Genellikle, bir nesnenin önünde bir engel olup olmadığını, bir merminin hedefe çarpıp çarpmadığını veya karakterin zemine değip değmediğini anlamak için kullanılırlar.
- Line Trace (Tek boyutlu algılama)
- Oyuncunun kamerası veya karakterinin önünden fırlatılan sanal bir ışındır. Bu ışının çarptığı ilk nesne, etkileşime uygun olup olmadığı kontrol edilir. Çoğu FPS veya TPS (üçüncü şahıs) oyunda bu yöntem tercih edilir.
- İki nokta arasında düz bir çizgi çizen ve bu çizgi üzerinde karşılaştığı ilk engeli veya nesneyi algılayan bir yöntemdir. En basit ve en yaygın kullanılan izleme (trace) metodudur.
- Başlangıç noktasından bitiş noktasına doğru bir çizgi (ışın) fırlatır. Bu çizgi, çarptığı ilk nesnenin bilgilerini (konum, normal yüzey açısı, çarpan nesne vb.) geri döndürür.
- Kullanımı
- Bir silahın namlusundan fırlayan bir merminin hedefe isabet edip etmediğini kontrol etmek,
- Üçüncü şahıs oyunlarında kameranın karakterin arkasındaki bir duvara çarpmasını engellemek,
- Bir karakterin önündeki bir nesneye (örneğin, bir kapı veya anahtar) bakıp bakmadığını anlamak.
- Daha yüksek preformans ve hız sağlar.
- Sphere Trace (Üç boyutlu algılama)
- Sphere Trace, bir küre şeklindeki hacmi başlangıç noktasından bitiş noktasına doğru hareket ettirerek algılama yapar. Line Trace'e göre daha geniş bir alanda çarpışma kontrolü yapma imkanı sunar.
- Başlangıç ve bitiş noktası arasında hareket eden bir kürenin (belirlenen bir yarıçapa sahip) yol boyunca herhangi bir nesneyle temas edip etmediğini kontrol eder. Eğer küre, yolculuğu sırasında bir nesneye çarparsa, bu çarpışmanın detaylarını döndürür.
- Kullanımı
- Bir patlamanın veya etrafa yayılan bir gücün belirli bir yarıçaptaki tüm düşmanlara zarar verip vermediğini kontrol etmek,
- Karakterin bir çıkıntının kenarında durup durmadığını veya dar bir alandan geçip geçemeyeceğini belirlemek,
- Karakterin zemine tam olarak değip değmediğini, özellikle karakterin kapsül (capsule) bileşeninin yeterli olmadığı durumlarda daha hassas bir kontrol sağlamak.
- Daha düşük preformans sağlar.
- Collision Box: Karakterin etrafına yerleştirilen bir tetikleyici alandır. Oyuncu bu alana girdiğinde, yakındaki etkileşebilir nesneler algılanır. Bu genellikle eşya toplama veya kapı açma gibi yakın mesafe etkileşimleri için idealdir.
Tetikleme (Triggering): Bir nesne algılandığında, oyuncu genellikle bir tuşa (örneğin, 'E' tuşu) basarak etkileşimi başlatır. Bu tuşa basıldığında, algılanan nesnenin Interact fonksiyonu çağrılır.
3. Kullanıcı arayüzü (HUD - Heads-Up Display)
Oyuncunun bir nesneyle etkileşime girebileceğini görsel olarak göstermek önemlidir.
HUD bildirimi: Oyuncu bir etkileşebilir nesnenin yakınına geldiğinde veya onu bir Line Trace ile işaret ettiğinde, ekranda bir "Etkileşim için 'E' tuşuna basın" gibi bir metin veya ikon belirmelidir. Bu, genellikle bir Widget Blueprint kullanılarak yapılır ve oyuncu nesneden uzaklaştığında veya başka bir nesneyi hedef aldığında gizlenir.
Çalışma akışı (Blueprint Örneği)
- Algılama (Player Blueprint): Oyuncu karakterinin Event Tick (her kare) döngüsünde sürekli olarak bir Line Trace veya Collision Overlap kontrolü çalıştırılır.
- Hedef belirleme: Line Trace sonucunda veya Collision Overlap olayında, çarpılan veya çakışan nesnenin bir etkileşim arayüzü (BPI_Interact gibi) uygulayıp uygulamadığı kontrol edilir.
- HUD güncelleme: Eğer nesne etkileşime uygunsa, bir HUD Widget'ı oluşturulur veya görünür hale getirilir. HUD, nesnenin ismini veya ne yapılacağını (örneğin "Kapıyı Aç") gösterebilir.
- Etkileşim tuşu: Oyuncu bir tuşa (örneğin 'E') bastığında, oyuncu karakterinin Blueprint'inde bu tuşun basılma olayı tetiklenir.
- Fonksiyon çağrısı: Bu olay tetiklendiğinde, son olarak algılanan nesnenin Interact fonksiyonu çağrılır. Nesne, bu fonksiyondaki kendi mantığını (örneğin, kapı animasyonunu oynatma, eşyayı envantere ekleme) çalıştırır.
- HUD temizliği: Etkileşim tamamlandığında veya nesneyle etkileşim kurulamadığında (örneğin oyuncu uzaklaştığında), HUD Widget'ı gizlenir veya ekrandan kaldırılır.
Unreal Engine'de bir etkileşim sistemi kurmak için aşağıdaki adımları sırasıyla uygulamaya çalışalım:
1. "Content\Game\Input\Actions" dizini içinde iken, sağ tıklayıp açılan menüden, "Input -> Input Action" seçeneğini seçerek yeni bir nesne oluşturalım ve adını "IA_Interact" olarak değiştirelim.
2. "Content\Input" dizinindeki "IMC_Default" nesnesine çift tıklayıp açtıktan sonra, "Details" sekmesinde:
- "Mappings" ifadesinin hemen sağında yer alan + butonuna tıklayarak yeni bir seçme kutusu ekleyelim.
- Seçme kutusundan "IA_Interact" değerini seçelim.
- Altta yer alan klavye resmine tıkladıktan sonra, klavyeden E tuşuna basarak atamayı yapalım.
Projemizde, etkileşim işlemlerini gerçekleştirmek amacıyla ilk olarak bir "Actor component" oluşturmamız gerekir.
1. "Content\Game\Blueprints" dizini altında iken, sağ tıklayınca açılan menüden "Blueprint Class" seçeneği ile açılan pencerede, "Actor Component" seçeneğini seçerek yeni bir nesne oluşturalım ve adını "BPC_Interact" olarak değiştirelim.
2. "BPC_Interact" nesnesine çift tıklayarak açalım.
3. "BPC_Interact" penceresinin "EventGraph" sekmesinde,
- "EnhancedInputAction IA_Interact" kutusu açalım.
- "EnhancedInputAction IA_Interact" kutusunun "Started" çıkışından bir "Sphere Trace By Channel" kutusu oluşturalım ("Line Trace By Channel" kutusu ile de aynı işlemleri yapabiliriz).
- Sağ tıkladığımızda açılan pencereden, "Get Owner" kutusu oluşturalım.
- "Get Owner" kutusunun "Return Value" çıkışından "Get Actor Location" kutusu oluşturalım.
- "Get Actor Location" kutusunun "Return Value" çıkışını "Sphere Trace By Channel" kutusunun "Start" girişine bağlayalım.
- "Get Player Camera Manager" kutusu oluşturalım.*
- "Get Player Camera Manager" kutusunun "Return Value" çıkışından "Get Camera Rotation" kutusu oluşturalım.*
- "Get Camera Rotation" kutusunun "Return Value" çıkışından "Multiply" kutusu oluşturalım.*
- "Multiply" kutusunun sol altındaki porta sağ tıklayıp "To Float (single-precision)" seçeneği ile Vector değerini Float değere çevirelim ve değeri 150 yapalım.
- "Get Actor Location" kutusunun "Return Value" çıkışından "Add" kutusu oluşturalım.
- "Multiply" kutusunun sağ üst port çıkışını "Add" kutusunun sol alt port girişine bağlayalım.
- "Add" kutusunun sağ üst port çıkışını "Sphere Trace By Channel" kutusunun "End" girişine bağlayalım.
- "Sphere Trace By Channel" kutusunun aşağıda gösterilen değerlerini değiştirelim:
- Radius -> 50
- Draw Debug Type -> For Duration
- "Sphere Trace By Channel" kutusunun "Return Value" çıkışından bir "Branch" kutusu oluşturalım.
- "Sphere Trace By Channel" kutusunun "Out Hit" çıkışından bir "Break Hit Result" kutusu oluşturalım.
Yukarıda, sağ tarafında * işareti yer alan satırlarla, kamera yönüne göre ayarlanan "Sphere Trace By Channel" kutusunun oluşturacağı kürenin yönünü, oyuncunun yönüne göre ayarlamak için, aşağıdaki satırları kullanabiliriz:
- "Get Owner" kutusunun "Return Value" çıkışından "Get Actor Rotation" kutusu oluşturalım.
- "Get Actor Rotation" kutusunun "Return Value" çıkışından "Get Forward Vector" kutusu oluşturalım.
- "Get Forward Vector" kutusunun "Return Value" çıkışından "Multiply" kutusu oluşturalım.
4. "BP_BasicCharacter" penceresinde, "+ Add" butonuna tıkladığımızda açılan pencerede, "BPC_Interact" değerini seçerek, "Components" sekmesine ekleyelim. Böylece, kullanıcı oyunda "E" tuşuna bastığında, "BP_BasicCharacter" nesnesine eklenen "BPC_Interact" nesnesi kullanarak, "EnhancedInputAction IA_Interact" zincirini tetikler.
Oyunda E tuşuna bastığımızda, oyuncunun önünde, karşımıza çıkan nesneleri algılamamızı sağlayan, kırmızı renkli bir küre görünür.
Blueprint Interface (Arayüz), temelde farklı Blueprint'ler arasında iletişim kurmak için kullanılan bir sözleşme veya protokol gibidir. Bir sınıfın doğrudan bir fonksiyonu çağırmak yerine, bir arayüz aracılığıyla konuşmasını sağlar.
Faydaları
- İletişim ve etkileşim: Diyelim ki bir oyunda kapılar, anahtarlar, düğmeler gibi birçok farklı etkileşime girilebilir nesneniz var. Bu nesnelerin hepsi "Etkileşim" diye bir şeyin gerçekleştiğini bilmeli. Bir Blueprint Interface kullanarak, OnInteract adında bir fonksiyon tanımlarsınız. Daha sonra hangi sınıf bu arayüzü uyguluyorsa, bu fonksiyona sahip olmak zorundadır. Böylece, oyuncu karakteri kapıya yaklaştığında, hangi türde nesne olursa olsun, sadece o nesne üzerindeki OnInteract fonksiyonunu çağırır.
- Esneklik ve genişletilebilirlik: Arayüzler, kodunuzu daha modüler ve yönetilebilir hale getirir. Bir nesne bir arayüzü uyguladığında, bu nesnenin başka hangi sınıftan miras aldığı veya ne tür bir nesne olduğu önemli değildir. Bu, yeni etkileşimli nesneler eklemeyi çok daha kolay hale getirir. Sadece arayüzü uygulamanız yeterlidir.
- Daha az bağımlılık: Arayüzler sayesinde, bir sınıfın başka bir sınıfa doğrudan bağımlı olmasını engellersiniz. Örneğin, oyuncu karakteri Blueprint'inizin her etkileşimli nesnenin türünü bilmesine gerek kalmaz. Sadece "Etkileşilebilir bir arayüz uygulayan bir nesne var mı?" diye sorar. Bu, kodunuzu daha temiz ve hatalara karşı daha dirençli yapar.
Özetle: Bir Blueprint Interface, farklı Blueprint sınıflarının birbirleriyle hangi fonksiyonlar üzerinden iletişim kurabileceğini tanımlayan bir şablondur. Bu, özellikle karmaşık oyun sistemlerinde esneklik, modülerlik ve sürdürülebilirlik sağlamak için vazgeçilmez bir araçtır.
Projede bir Blueprint Interface oluşturmak için aşağıdaki adımları sırasıyla gerçekleştirelim:
- "Content\Game\Blueprints" dizini içinde iken, sağ tıklayınca açılan menüden "Blueprint -> Blueprint Interface" seçeneğini seçerek, yeni bir nesne oluşturalım ve adını "BPI_Interact" olarak değiştirelim.
- "BPI_Interact" nesnesini çift tıklayarak açalım ve fonksiyon adını "Interact" olarak değiştirelim.
- "BPC_Interact" penceresinin "EventGraph" sekmesinde,
- "Break Hit Result" kutusunun "Hit Actor" çıkışından "Interact (Message)" kutusu açalım.
- "Branch" kutusunun "True" çıkışını "Interact" kutusuna bağlayalım.
1. "Content\Game\Blueprints" dizini içinde iken, sağ tıklayınca açılan menüden "Blueprint Class" seçeneği ile açılan pencerede, "Actor" seçeneği ile bir "Actor" oluşturarak adını "BP_Sphere" olarak değiştirelim.
2. "BP_Sphere" penceresinde,
- "+ Add" butonu ile bir "Sphere" oluşturalım.
- "Class Settings" sekmesinde "Implemented Interfaces" satırında "Add" kutusundan "BPI_Interact" değerini seçerek, sol tarafta "INTERFACES" bölümü altına ekleyelim.
- "INTERFACES" bölümü altındaki "Interact" değerine çift tıklayarak, "EventGraph" sekmesi altında "Event Interact" kutusu oluşturalım.
- "Event Interact" kutusunun çıkışından "Destroy Actor" kutusu oluşturalım.
3. "BasicLevel" penceresinde, "Content\Game\Blueprints" dizinindeki "BP_Sphere" nesnesini sürükleyip sahneye bırakalım.
Oyuncu, küreye yaklaşıp "E" tuşuna bastığında küre yok olur. İşlemler aşağıdaki sırayla gerçekleşir:
- "BP_BasicCharacter" nesnesine eklenen "BPC_Interact" nesnesi kullanarak, "EnhancedInputAction IA_Interact" zincirini tetikler.
- Kamera bakış yönünde "Sphere Trace by Channel" kutusu tarafından oluşturulan küre, sahnedeki "BP_Sphere" küresi ile kesiştiğinden, "Sphere Trace by Channel" kutusu çıkışına bağlı "Branch" kutusunun "True" çıkışına bağlı "Interact" kutusu tetiklenir.
- "BPI_Interact" içindeki "Interact" fonksiyonu devreye girer.
- "BP_Sphere" içinde oluşturulan "Interact" arayüzü ile oluşturulan "Event Interact" kutusundan oluşturulan "Destroy Actor" kutusu ile sahnede yer alan "BP_Sphere" nesnesi yok edilir.
Oluşturup sahneye eklediğimiz "BP_Sphere" adlı "Actor" içine eklenen "Interact" adlı fonksiyon arayüzü ile oluşturulan "Event Interact" kutusuna, "Interact" adlı arayüz fonksiyonu çağrıldığında, "BP_Sphere" için devreye girecek olan işlemler eklenir. Yani her bir aktör için aynı arayüz fonksiyonu adı altında farklı işlemler yapılabilir.
Projemize bir ışık kaynağı Actor nesnesi eklemek için aşağıdaki işlemleri sırasıyla uygulayalım:
1. "Content\Game\Blueprints" dizini içinde iken, sağ tıklayınca açılan menüden "Blueprint Class" seçeneği ile açılan pencerede, "Actor" seçeneği ile bir "Actor" oluşturarak adını "BP_Light" olarak değiştirelim.
2. "BP_Light" penceresinde,
- "DefaultSceneRoot" altına "PointLight" ve "PointLight" altına ise bir StaticMesh oluşturalım.
- StaticMesh'i "DefaultSceneRoot" üzerine sürükleyip bırakarak "Root" yapalım.
- StaticMesh'in "Static Mesh" değerini "SM_Lamp_Ceiling" yapalım.
- PointLight'ın Location Z değerini -150 yapalım.
- BP_LightSource'u sürükleyip sahneye bırakalım.
- PointLight'ın "Intensity" değerini 5.000'den 20.000'e yükseltelim (Sahnede daha parlak görünmesi için).
- "Class Settings" sekmesinde "Implemented Interfaces" satırında "Add" kutusundan "BPI_Interact" değerini seçerek, sol tarafta "INTERFACES" bölümü altına ekleyelim.
- "INTERFACES" bölümü altındaki "Interact" değerine çift tıklayarak, "EventGraph" sekmesi altında "Event Interact" kutusu oluşturalım.
- "Event Interact" kutusunun çıkışından "Set Visibility (PointLight)" kutusu oluşturalım.
- "Point Light" kutusunun çıkışından "Is Visible" kutusu oluşturalım.
- "Is Visible" kutusunun çıkışından "NOT" kutusu oluşturalım.
- "NOT" kutusunun çıkışını "Set Visibility" kutusunun "New Visibility" girişine bağlayalım.
3. "BasicLevel" penceresinde, "Content\Game\Blueprints" dizinindeki "BP_Light" nesnesini sürükleyip sahneye bırakalım.
Oyuncu, "BP_Light" nesnesine yaklaşıp "E" tuşuna bastığında lamba yanar, tekrar bastığında söner. İşlemler aşağıdaki sırayla gerçekleşir:
- "BP_BasicCharacter" nesnesine eklenen "BPC_Interact" nesnesi kullanarak, "EnhancedInputAction IA_Interact" zincirini tetikler.
- Kamera bakış yönünde "Sphere Trace by Channel" kutusu tarafından oluşturulan küre, sahnedeki "BP_Light" nesnesi ile kesiştiğinden, "Sphere Trace by Channel" kutusu çıkışına bağlı "Branch" kutusunun "True" çıkışına bağlı "Interact" kutusu tetiklenir.
- "BPI_Interact" içindeki "Interact" fonksiyonu devreye girer.
- "BP_Light" içinde oluşturulan "Interact" arayüzü ile oluşturulan "Event Interact" kutusundan oluşturulan "Set Visibility" kutusu devreye girer.
"BP_Light" için etkileşim sistemi "BP_Sphere" ile aynı şekilde çalışmaktadır.
1. "Content\Game\Blueprints" dizini içinde iken, sağ tıklayınca açılan menüden "Blueprint Class" seçeneği ile açılan pencerede, "Actor" seçeneği ile bir "Actor" oluşturarak adını "BP_Cube" olarak değiştirelim.
2. "BP_Cube" penceresinde,
- "+ Add" butonu ile bir "Cube" oluşturalım.
- "Class Settings" sekmesinde "Implemented Interfaces" satırında "Add" kutusundan "BPI_Interact" değerini seçerek, sol tarafta "INTERFACES" bölümü altına ekleyelim.
- "INTERFACES" bölümü altındaki "Interact" değerine çift tıklayarak, "EventGraph" sekmesi altında "Event Interact" kutusu oluşturalım.
- "Event Interact" kutusunun çıkışından bir "Print String" kutusu oluşturup değerini "Cube triggered!" yapalım.
- "Actor" veri türünden (Object Reference) "activatedActor" adlı bir değişken oluşturalım ve değişkeni "Public" yapalım.
- "activatedActor" değişkeninden bir "GET" kutusu oluşturalım.
- "Activated Actor" kutusundan "Interact (Message)" kutusu oluşturalım.
- "Print String" kutusunun çıkışını "Interact" kutusuna bağlayalım.
3. "BasicLevel" penceresinde,
- "Content\Game\Blueprints" dizinindeki "BP_Cube" nesnesini sürükleyip sahneye bırakalım.
- "Content\Game\Blueprints" dizinindeki "BP_Light" nesnesini sürükleyip kübün yukarısına sahneye bırakalım. Otomatik olarak "BP_Light2" adını alacaktır.
- "BP_Cube" nesnesi seçili iken, "Details" sekmesinde, "Actor to Activate" satırının sağındaki "Pick Actor from scene" butonuna tıkladıktan sonra, sahnedeki "BP_Light2" nesnesine tıklayarak seçelim.
Bu durumda, oyuncu, kübe yaklaşıp "E" tuşuna bastığında lamba yanar, tekrar bastığında söner. İşlemler aşağıdaki sırayla gerçekleşir:
- "BP_BasicCharacter" nesnesine eklenen "BPC_Interact" nesnesi kullanarak, "EnhancedInputAction IA_Interact" zincirini tetikler.
- Kamera bakış yönünde "Sphere Trace by Channel" kutusu tarafından oluşturulan küre, sahnedeki "BP_Cube" küresi ile kesiştiğinden, "Sphere Trace by Channel" kutusu çıkışına bağlı "Branch" kutusunun "True" çıkışına bağlı "Interact" kutusu tetiklenir.
- "BPI_Interact" içindeki "Interact" fonksiyonu devreye girer.
- "BP_Cube" içinde oluşturulan "Interact" arayüzü ile oluşturulan "Event Interact" kutusundan oluşturulan "Print String" kutusu ile "Cube triggered!" ifadesi ekrana yazılır.
- "Interact" kutusu ile "BP_Light" nesnesinin "Event Interact" zinciri tetiklenir ve "BP_Light2" lambası yanar.
"BasicLevel" penceresinde, "Content\StarterContent\Architecture" dizininde bulunan aşağıdaki nesneleri karşılarında gösterilen miktar kadar kullanarak bir oda oluşturalım:
- Wall_Door_400x300 (2 adet) - Ön ve arka duvar için
- Wall_400x300 (3 adet) - Yan duvarlar ve çatı için
Projemize bir kapı Actor nesnesi eklemek için aşağıdaki işlemleri sırasıyla uygulayalım:
1. "Content\Game\Blueprints" dizini içinde iken, sağ tıklayınca açılan menüden "Blueprint Class" seçeneği ile açılan pencerede, "Actor" seçeneği ile bir "Actor" oluşturarak adını "BP_Door" olarak değiştirelim.
2. "BP_Door" penceresinde,
- "DefaultSceneRoot" altına bir "StaticMesh" oluşturalım.
- StaticMesh'i "DefaultSceneRoot" üzerine sürükleyip bırakarak "Root" yapalım.
- StaticMesh'in adını "SM_DoorFrame" olarak değiştirelim, "Static Mesh" değerini "SM_DoorFrame" yapalım.
- "SM_DoorFrame" altında yeni "StaticMesh" oluşturalım ve adını "SM_Door" olarak değiştirelim.
- "SM_Door" nesnesinin "Static Mesh" değerini "SM_Door" yapalım.
- "SM_DoorFrame" altında yeni "Collision Box" oluşturalım ve adını "Trigger" olarak değiştirip aşağıdaki değerleri değiştirelim.
- Location -> 0,0 0,0 110,0
- Scale -> 1,5 2,1 3,4
- "EventGraph" içinde, "OpenDoor" ve "CloseDoor" adlı iki adet "Custom Event" oluşturalım.
- "OpenDoor" kutusunun çıkışına "Add Timeline" yazarak çıkan değeri seçip bir "Timeline" kutusu açalım.
- Timeline'a çift tıklayınca açılan "Timeline_Template" penceresinde, "Track" butonuna tıklayınca açılan kutudan "Add Float Track" seçeneğine tıklayalım.
- "NewTrack_0" değerini "Angle" olarak değiştirelim.
- 0 çizgisine sağ tıklayıp "Add key to ..." seçeneğine tıklayınca çıkan "Time" değerini 0 ve "Value" değerini 0 yapalım.
- 0 çizgisine tekrar sağ tıklayıp "Add key to ..." seçeneğine tıklayınca çıkan "Time" değerini 2 ve "Value" değerini -140 yapalım.
- "Track" butonu sağında yer alan "Length" değerini 2.00 yapalım.
- "OpenDoor" kutusunun hemen sağına bir adet "SM_Door" değişkeni kutusu açalım.
- "SM_Door" kutusunun çıkışından "Set Relative Rotation" kutusu açalım.
- "Set Relative Rotation" kutusunun "New Rotation" değerine sağ tıklayıp "Split Struct Pin" değerini seçerek X, Y ve Z değerleri elde edelim.
- "Timeline" kutusunun "Angle" port çıkışını "Set Relative Rotation" kutusunun "New Rotation Z" girişine bağlayalım.
- "Timeline" kutusunun "Finished" port çıkışından "Switch on ETimelineDirection" kutusu oluşturalım.
- "Timeline" kutusunun "Direction" port çıkışını "Switch on ETimelineDirection" kutusunun "Direction" girişine bağlayalım.
- "CloseDoor" kutusunu "Timeline" kutusunun "Reverse" girişine bağlayalım.
- Kapı açma ve kapatma işlemlerine ses eklemek için,
- "Set Relative Rotation" kutusunun çıkışından bir "Play Sound at Location" kutusu oluşturalım.
- Bir "Get Actor Location" kutusu oluşturup, "Return Value" çıkışını "Play Sound at Location" kutusunun "Location" girişine bağlayalım.
- "Play Sound at Location" kutusunun "Sound" değerini "Dockable_Window_Open" olarak belirleyelim.
- "Trigger" nesnesi seçili iken.
- "Details" sekmesinde "Events" satırı altındaki "On Component Begin Overlap" satırının sağındaki + butonuna tıklayarak, "On Component Begin Overlap (Trigger)" kutusu oluşturalım.
- "On Component Begin Overlap (Trigger)" kutusunun "Other Actor" portundan bir "Actor Has Tag" kutusu oluşturalım ve kutunun "Tag" değerini "Player" olarak değiştirelim.
- "Actor Has Tag" kutusunun "Return Value" çıkışından bir "Branch" kutusu oluşturalım.
- "On Component Begin Overlap (Trigger)" kutusunun çıkışını "Branch" kutusuna bağlayalım.
- "Branch" kutusunun "True" port çıkışından bir "Print String" kutusu oluşturup değerini "Open door!" ve rengini yeşil olarak değiştirelim.
- "Print String" kutusunun çıkışından bir "Open Door" kutusu oluşturalım.
- "Details" sekmesinde "Events" satırı altındaki "On Component End Overlap" satırının sağındaki + butonuna tıklayarak, "On Component End Overlap (Trigger)" kutusu oluşturalım.
- "On Component End Overlap (Trigger)" kutusunun "Other Actor" portundan bir "Actor Has Tag" kutusu oluşturalım ve kutunun "Tag" değerini "Player" olarak değiştirelim.
- "Actor Has Tag" kutusunun "Return Value" çıkışından bir "Branch" kutusu oluşturalım.
- "On Component End Overlap (Trigger)" kutusunun çıkışını "Branch" kutusuna bağlayalım.
- "Branch" kutusunun "True" port çıkışından bir "Print String" kutusu oluşturup değerini "Close door!" ve rengini kırmızı olarak değiştirelim.
- "Print String" kutusunun çıkışından bir "Close Door" kutusu oluşturalım.
3. "Content\StarterContent\Props" altında "SM_Door" nesnesini çift tıklayarak açalım ve üstteki "Collision" menüsünden "Add Box Simplified Collision" seçeneğine tıklayıp basit bir collision sistemi ekleyelim. Böylece, kapı açık olmadıkça oyuncu kapıdan geçiş yapamaz.
4. "BasicLevel" penceresinde, "Content\Game\Blueprints" dizinindeki "BP_Door" nesnesini sürükleyip sahnede odanın girişine ve çıkışına birer adet bırakalım. Girişe bıraktığımız kapıyı 180 derece döndürelim.
Oyuncu, odanın girişindeki "BP_Door" ve çıkışındaki "BP_Door2" kapılarına yaklaştığında kapı yavaşça açılır, kapıdan çıktıktan sonra aynı şekilde kapanır.
Ancak, odanın ilk kapısından girişte kapı oyuncunun gidiş yönünde açılmasına rağmen, aynı kapıdan ters yönde geçmeye çalıştığında, kapı gidiş yönünün tersine açılır. İkinci kapı ise, girişte kapı oyuncunun gidiş yönünün tersine, aynı kapıdan ters yönde geçmeye çalıştığında, kapı gidiş yönünde açılır.
5. Kapının, oyuncu hangi taraftan girerse girsin, daima oyuncunun gidiş yönünde açılması için, "BP_Door" penceresinde aşağıdaki işlemleri sırasıyla uygulayalım.
- "directionDoor" adlı "Integer" bir değişken oluşturalım.
- "Timeline" kutusunun sağında bir "Multiply" kutusu oluşturalım.
- "Timeline" kutusunun "Angle" çıkışını "Multiply" kutusunun sol üst portuna bağlayalım.
- "directionDoor" değişkenini sürükleyip sahneye bırakarak bir "GET" kutusu oluşturalım.
- "Direction Door" kutusunun çıkışını "Multiply" kutusunun sol alt portuna bağlayalım.
- "Multiply" kutusunun çıkışını "Set Relative Rotation" kutusunun "New Rotation Z" portuna bağlayalım.
- "Add Custom Event" kutusu oluşturarak adını "SetDirection" olarak değiştirelim.
- "SetDirection" kutusunun sağına bir "Branch" kutusu oluşturarak, "SetDirection" kutusunun çıkışını bu kutuya bağlayalım.
- Bir "Get Player Character" kutusu oluşturalım.
- "Get Player Character" kutusunun çıkışından bir "Get Actor Location" kutusu oluşturalım ve "Return Value" değerine sağ tıklayıp "Split Struct Pin" seçeneği ile X, Y ve Z değerlerini elde edelim.
- "SM_Door" nesnesini sürükleyip sahneye bırakarak bir kutu oluşturalım.
- "SM Door" kutusunun çıkışından "Get Owner" kutusu oluşturalım.
- "Get Owner" kutusu "Return Value" çıkışından bir adet "Get Actor Location" ve bir adet "Get Actor Rotation" kutusu oluşturalım ve her iki kutuda ve "Return Value" değerlerine sağ tıklayıp "Split Struct Pin" seçeneği ile X, Y ve Z değerlerini elde edelim (Sadece "Get Actor Transform" kutusu kullanarak bu işlemleri gerçekleştirebiliriz).
- "Get Actor Rotation" kutusunun "Return Value Z" çıkışından bir adet "Not Equal (!=)" ve bir adet "Equal (==)" kutusu oluşturalım.
- "Get Owner" kutusuna bağlı "Get Actor Location" kutusunun "Return Value X" çıkışından bir adet "Less (<)" ve bir adet "Greater (>)" kutusu oluşturalım.
- "<" ve ">" kutularını diğer portlarını, "Get Player Character" kutusuna bağlı "Get Actor Location" kutusunun "Return Value X" portuna bağlayalım.
- Bir "AND" kutusu oluşturup, "<" ve "!=" kutularının çıkışlarını bu kutuya bağlayalım.
- Bir "AND" kutusu oluşturup, ">" ve "==" kutularının çıkışlarını bu kutuya bağlayalım.
- Bir "OR" kutusu oluşturup, "END" kutularının çıkışlarını bu kutuya bağlayalım.
- "OR" kutusunun çıkışını "Branch" kutusunun "Condition" girişine bağlayalım.
- "Branch" kutusunun sağında "directionDoor" değişkeninden 2 adet "SET" kutusu, ilkinin değeri 1 ikincisinin değeri -1 olmak üzere, oluşturalım.
- "Branch" kutusunun "True" port çıkışını ilk ve "False" port çıkışını ikinci "SET" kutusuna bağlayalım.
- "On Component Begin Overlap (Trigger)" zincirinde, "Print String" kutusundan sonra "Set Direction" kutusu oluşturup "Open Door" kutusuna bağlayalım.
Böylece, oyuncu kapılara hangi yönden giriş yaparsa yapsın, kapılar, oyuncunun gidiş yönünde açılır.
"BasicLevel" sahnesine bir buton ve 3 lamba ekleyerek, oyuncu butonun yakınında iken, kullanıcının 'E' tuşuna basarak 3 lambayı birden yakmasını ve söndürmesini sağlamak için aşağıdaki işlemleri sırasıyla uygulayalım:
1. "Content\Game\Blueprints" dizini içinde iken, sağ tıklayınca açılan menüden "Blueprint Class" seçeneği ile açılan pencerede, "Actor" seçeneği ile bir "Actor" oluşturarak adını "BP_Button" olarak değiştirelim.
2. "BP_Button" penceresinde,
- "+ Add" butonu ile bir "Cube" oluşturalım ve adını "Button" olarak değiştirelim.
- "Class Settings" sekmesinde "Implemented Interfaces" satırında "Add" kutusundan "BPI_Interact" değerini seçerek, sol tarafta "INTERFACES" bölümü altına ekleyelim.
- "INTERFACES" bölümü altındaki "Interact" değerine çift tıklayarak, "EventGraph" sekmesi altında "Event Interact" kutusu oluşturalım.
- "Event Interact" kutusunun çıkışından bir "Print String" kutusu oluşturup değerini "Button triggered!" yapalım.
- Sol alt taraftan, "OnButtonTriggered" adlı bir "Event Dispatcher" oluşturalım. Böylece, buton aktif hale geldiğinde, "OnButtonTriggered" nesnesini çağırarak sinyal yollayıp diğer Actor sınıflarını haberdar etmiş oluruz. Event Dispatcher'lar, bir olayın meydana geldiğini duyurmamıza ve bu olaya "abone olan" tüm aktörlerin tepki vermesini sağlamamıza olanak tanır.
- "OnButtonTriggered" nesnesini sürükleyip alttaki "Print String" kutusunun sağına bırakalım. Otomatik olarak açılan menüde "Call" seçeneğine tıklayalım. "Call On BUtton Triggered" kutusu oluşturulur.
- "Print String" kutusunun çıkışını "Call On BUtton Triggered" kutusunun girişine bağlayalım.
3. "BP_Light" penceresinde,
- "BP_Button" cinsinden "Button" adlı public bir değişken oluşturalım (Object reference).
- "EventGraph" sekmesinde,
- "Button" değişkenini sürükleyip "Event BeginPlay" kutusunun sağına bırakalım.
- "Button" kutusunun sağına "? Is Valid" kutusu açıp, "Event BeginPlay" kutusunun çıkışını bu kutunun girişine bağlayalım.
- "Button" kutusundan "Bind Event to On Button Triggered" kutusu açalım. "? Is Valid" kutusunun çıkışını bu kutusunun girişine bağlayalım.
- "Button" kutusunun çıkışını "Bind Event to On Button Triggered" kutusunun "Target" portuna bağlayalım.
- "Bind Event to On Button Triggered" kutusunun "Event" portundan "Custom Event" oluşturarak adını "TurnLightOnOff" olarak değiştirelim.
- "TurnLightOnOff" kutusunun çıkışını "Event Interact" zincirindeki "Set Visibility" kutusunun girşine bağlayalım.
4. "BasicLevel" penceresinde,
- "Content\Game\Blueprints" dizinindeki "BP_Button" nesnesini sürükleyip sahneye bırakalım.
- "Content\Game\Blueprints" dizinindeki "BP_Light" nesnesini 3 defa sürükleyip, kübün yukarısına sahneye bırakalım. Yeni oluşturduğumuz nesneler otomatik olarak "BP_Light3", "BP_Light4" ve "BP_Light5" adını alacaktır.
- Sahnede, "BP_Light3", "BP_Light4" ve "BP_Light5" nesnelerini sırasıyla seçip, her bir nesne için, "Details" sekmesinde "Default" satırı altındaki "Button" satırındaki "Pick Actor from scene" butonuna tıklayarak sahneden "BP_Button" nesnesini seçelim.
Bu durumda, oyuncu, "BP_Button" nesnesine yaklaşıp "E" tuşuna bastığında 3 lamba birlikte yanar, tekrar bastığında söner. İşlemler aşağıdaki sırayla gerçekleşir:
- "BP_BasicCharacter" nesnesine eklenen "BPC_Interact" nesnesi kullanarak, "EnhancedInputAction IA_Interact" zincirini tetikler.
- Kamera bakış yönünde "Sphere Trace by Channel" kutusu tarafından oluşturulan küre, sahnedeki "BP_Cube" küresi ile kesiştiğinden, "Sphere Trace by Channel" kutusu çıkışına bağlı "Branch" kutusunun "True" çıkışına bağlı "Interact" kutusu tetiklenir.
- "BPI_Interact" içindeki "Interact" fonksiyonu devreye girer.
- "BP_Button" içinde oluşturulan "Interact" arayüzü ile oluşturulan "Event Interact" kutusundan oluşturulan "Print String" kutusu ile "Button triggered!" ifadesi ekrana yazılır.
- "Call On Button Triggered" kutusu ile, "OnButtonTriggered" olayı devreye girer bu Event'e "abone olan" tüm lambalar aynı anda tepki verir.
- Sahnede yer alan her bir lamba (BP_Light), oyun başladığında (Event BeginPlay), kendisine referans olarak verdiğimiz butona (BP_Button) gider ve "Butonun 'OnButtonTriggered' Event'i tetiklendiğinde benim 'TurnLightOnOff' Event'imi çalıştır" talimatı verir.

"BasicLevel" penceresinde aşağıdakine benzer bir görüntü oluşacaktır: